【问题标题】:Django - Celery: @transaction and @task don't stackDjango - Celery:@transaction 和 @task 不堆叠
【发布时间】:2011-09-08 15:03:15
【问题描述】:

我想运行一个带有手动事务管理的 Django - Celery 任务,但注释似乎没有堆叠。

例如

def ping():
    print 'ping'
    pong.delay('arg')

@task(ignore_result=True)
@transaction.commit_manually()
def pong(arg):
    print 'pong: %s' % arg
    transaction.rollback()

结果

TypeError: pong() got an unexpected keyword argument 'task_name'

而反向注释顺序导致

---> 22     pong.delay('arg')

AttributeError: 'function' object has no attribute 'delay'

这是有道理的,但我很难找到一个好的解决方法。 Django 文档没有提到注释的替代方案,当我不需要时,我不想为每个 celery 任务创建一个类。

有什么想法吗?

【问题讨论】:

    标签: django celery django-celery


    【解决方案1】:

    以前 Celery 有一些神奇之处,其中一组默认关键字参数 如果接受它们,则将其传递给任务。

    从 2.2 版开始,您可以禁用此行为,但最简单的方法是 从celery.task而不是celery.decorators导入task装饰器:

    from celery.task import task
    
    @task
    @transaction.commit_manually
    def t():
        pass
    

    decorators 模块已弃用,将在 3.0 中完全删除, “魔术关键字参数”也是如此

    注意: 对于自定义任务类,您应该将 accept_magic_kwargs 属性设置为 False:

    class MyTask(Task):
        accept_magic_kwargs = False
    

    注意 2:确保您的自定义装饰器使用 functools.wraps 保留函数的名称,否则任务将以错误的名称结束。

    【讨论】:

    • 这正是我所希望的!谢谢!
    【解决方案2】:

    任务装饰器从您的函数中生成一个class x(Task),并将run 方法作为您的目标。建议你定义类和装饰方法。

    未经测试,例如:

    class pong(Task):
      ignore_result = True
    
      @transaction.commit_manually()
      def run(self,arg,**kwargs):
        print 'pong: %s' % arg
        transaction.rollback()
    

    【讨论】:

    • 希望找到一种非类的方法来做到这一点,但我想这是最好的选择。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 2019-11-11
    • 1970-01-01
    • 2021-03-09
    • 2013-06-19
    • 1970-01-01
    相关资源
    最近更新 更多