将类方法用作Celery任务
我正在尝试使用类的方法作为django-celery的任务,并通过@task装饰器来标记它们。类似的情况在这里被Anand Jeyahar提到过。大概是这样的:
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任务。 - 我试着找出如何动态注册任务,比如从构造函数中注册,但celery在工作进程之间共享代码,所以这似乎是不可能的。
谢谢你的帮助!
5 个回答
5
当你有了:
a = A()
你可以这样做:
A.foo.delay(a, param0, .., paramN)
谢谢!
11
Jeremy Satterfield 有一个简单明了的教程,教你如何写基于类的任务,如果你想这样做,可以在这里查看。
这个方法的关键在于扩展 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
这一部分是否必要。
55
从3.0版本开始,Celery开始实验性地支持将方法作为任务来使用。
关于这方面的说明可以在celery.contrib.methods
中找到,里面也提到了一些需要注意的事项:
https://docs.celeryproject.org/en/3.1/reference/celery.contrib.methods.html
请注意:从4.0版本开始,Celery不再支持contrib.methods
。