从现有的装饰器创建一个新的装饰器

时间:2020-01-07 14:07:03

标签: python python-decorators dramatiq

我在任务队列中使用dramatiq,该队列提供装饰器@dramatiq.actor来装饰一个函数作为任务。我尝试编写自己的包装器来包装@dramatiq.actor装饰器,因此可以向适用于所有任务的@dramatiq.actor装饰器添加默认参数(我正在谈论的参数是{{1 }}。

由于某种原因,我遇到以下错误:

priority=100

如果我将自定义TypeError: foobar() takes 1 positional argument but 3 were given 装饰器切换为@task可以正常工作,那么我猜我的自定义装饰器是不正确的,但我无法发现我的错误。

decorators.py

@dramatiq.actor

tasks.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)

views.py

@task
def foobar(entry_pk):
    ...

2 个答案:

答案 0 :(得分:3)

使用functools.partial会容易得多:

from functools import partial

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

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

这使您可以抢先向函数添加参数,而无需实际调用它。

答案 1 :(得分:0)

另一种方法是子类Dramatiq的类并覆盖actor方法。该方法以及此处介绍的其他一些技巧-https://blog.narrativ.com/converting-celery-to-dramatiq-a-py3-war-story-23df217b426