使用类方法作为芹菜任务

时间:2012-02-12 16:12:53

标签: python django-celery

我正在尝试使用class的方法作为django-celery任务,使用@task装饰器进行标记。 Anand Jeyahar问道,同样的情况被here所描述。 就像这样

class A:
    @task
    def foo(self, bar):
        ...

def main():
    a = A()
    ...
    # what i need
    a.foo.delay(bar) # executes as celery task 
    a.foo(bar) # executes locally

问题是,即使我使用类a.foo.delay(bar)这样的类实例,它表示foo至少需要两个参数,这些参数会导致self指针未命中。

更多信息:

  • 由于继承,我无法将类转换为模块
  • 方法强烈依赖于类成员,所以我不能使它们静态
  • 标记为@task装饰器的任务使得该类本身成为一个任务,并且可以从run()方法执行方法,使用一些参数作为键方法选择,但它并不完全是我想要的。
  • 创建类的实例并将其作为self参数传递给方法会改变我执行方法而不是作为celery taks的方式,而是像通常的方法(即测试时)
  • 我试图找出如何从构造函数中注册任务,但是celery在工作者之间共享代码,这就是为什么它似乎是不可能的。

感谢您的帮助!

5 个答案:

答案 0 :(得分:47)

自3.0版以来,Celery一直支持将方法用作任务。

此文档位于celery.contrib.methods,并且还提到了一些您应该注意的警告:

http://docs.celeryproject.org/en/latest/reference/celery.contrib.methods.html

请注意:支持自{4.0}已从Celery 中移除

答案 1 :(得分:7)

Jeremy Satterfield有一个干净而直接的教程来编写基于类的任务,如果这是你想要完成的。您可以查看here

魔术基本上是扩展celery.Task类,包括run()方法,如下所示:

from celery import Task

class CustomTask(Task):
    ignore_result = True

    def __init__(self, arg):
        self.arg = arg

    def run(self):
        do_something_with_arg(self.arg)

然后像这样运行任务:

your_arg = 3

custom_task = CustomTask()
custom_task.delay(your_arg)

我不确定ignore_result = True部分是否必要BTW。

答案 2 :(得分:4)

当你有:

    a = A()

你可以这样做:

    A.foo.delay(a, param0, .., paramN)

干杯

答案 3 :(得分:1)

对我来说唯一有效的是celery.current_app,因为这只是将self传递给方法。

所以这应该是这样的:

from celery import current_app
from celery.contrib.methods import task_method

class A:
@current_app.task(filter=task_method, name='A.foo')
def foo(self, bar):
    ...

如果在不同的类中使用相同名称的方法,则必须使用该名称。

答案 4 :(得分:0)

我遇到了类似的情况,决定将类方法包装在一个简单的函数中,该函数将其参数重定向到该类的实例及其执行方法:

class A:
    def foo(self, bar):
       # do this

a = A()

@app.task
def a_wrapper(bar):
    return a.foo(bar)

# probably in a different size with an import in-place:

a_wrapper.delay(bar)