Создать новый декоратор из существующего - PullRequest
2 голосов
/ 07 января 2020

Я использую dramatiq для своей очереди задач, которая предлагает декоратору @dramatiq.actor для украшения функции как задачи. Я попытался написать свой собственный декоратор, который упаковывает декоратор @dramatiq.actor, чтобы я мог добавить аргумент по умолчанию к декоратору @dramatiq.actor, который применяется ко всем задачам (аргумент, о котором я говорю, это priority=100).

По какой-то причине я получаю следующую ошибку:

TypeError: foobar() takes 1 positional argument but 3 were given

Если я переключаю свой собственный @task декоратор на @dramatiq.actor, это работает, так что я думаю, что мой собственный декоратор не верен но я не могу определить свою ошибку.

decorators.py

def task(func=None, **kwargs):    
    def decorator(func):
        @wraps(func)
        @dramatiq.actor(priority=100, **kwargs)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)

        return wrapper

    if func is None:
        return decorator

    return decorator(func)

tasks.py

@task
def foobar(entry_pk):
    ...

views.py

foobar.send_with_options(args=(entry.pk,))

Ответы [ 2 ]

3 голосов
/ 07 января 2020

Было бы намного проще использовать functools.partial:

from functools import partial

task = partial(dramatiq.actor, priority=100)

@task
def foobar(*args, **kwargs):
    ...

Это позволяет вам превентивно добавлять аргумент в функцию, фактически не вызывая ее .

0 голосов
/ 29 января 2020

Другой подход заключается в создании подкласса класса Dramatiq и переопределении метода actor. Этот подход плюс некоторые другие советы, описанные здесь - https://blog.narrativ.com/converting-celery-to-dramatiq-a-py3-war-story-23df217b426

...