简体   繁体   English

使用类方法作为芹菜任务

[英]using class methods as celery tasks

I'm trying to use the methods of class as the django-celery tasks, marking it up using @task decorator.我正在尝试使用类的方法作为 django-celery 任务,使用 @task 装饰器对其进行标记。 The same situation is discribed here , asked by Anand Jeyahar. 此处描述了相同的情况,由 Anand Jeyahar 询问。 It's something like this是这样的

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

The problem is even if i use class instance like this a.foo.delay(bar) it says, that foo needs at least two arguments, which meens that self pointer misses.问题是即使我使用这样的类实例a.foo.delay(bar)它说, foo至少需要两个参数,这意味着self指针未命中。

More information:更多信息:

  • I can't convert class to module because of inheritance由于继承,我无法将类转换为模块
  • Methods are strongly depended on class members, so i can't make them static方法强烈依赖于类成员,所以我不能将它们设为静态
  • Marking class as the task with @task decorator makes the class a task itself, and it could be possible to execute the methods from run() method, using some argument as a key for method selection, but it's not exactly what i want.标记与@task装饰任务,使类任务本身,它可能是能够执行从方法run()方法,使用一些参数为方法选择的关键,但它不正是我想要的。
  • Creating an instance of class and passing it as self argument to methods changes the way i execute the methods not as celery taks, but as usual methods (ie while testing)创建类的实例并将其作为self参数传递给方法改变了我执行方法的方式,而不是像 celery taks 那样,而是像通常的方法一样(即在测试时)
  • I've tried to find out how i can register the task dinamically, from constructor for example, but celery shares the code between the workers, so that's why it seems to be impossible.我试图找出如何以动态方式注册任务,例如从构造函数,但芹菜在工人之间共享代码,所以这似乎是不可能的。

Thanks for your help!谢谢你的帮助!

Celery has experimental support for using methods as tasks since version 3.0. Celery 从 3.0 版本开始对使用方法作为任务提供实验支持。

The documentation for this is in celery.contrib.methods , and also mentions some caveats you should be aware of:这方面的文档在celery.contrib.methods ,并且还提到了一些您应该注意的警告:

https://docs.celeryproject.org/en/3.1/reference/celery.contrib.methods.html https://docs.celeryproject.org/en/3.1/reference/celery.contrib.methods.html

Be aware : support for contrib.methods removed from Celery since 4.0请注意自 4.0 以来,contrib.methods支持已从 Celery 中移除

Jeremy Satterfield has a clean and straight forward tutorial to write class based tasks if that's what you want to accomplish. Jeremy Satterfield 有一个干净而直接的教程来编写基于类的任务,如果这是你想要完成的。 You can check it here .你可以在这里查看

The magic is basically extending celery.Task class including a run() method, like something like this:魔法基本上是扩展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)

and then run the task like this:然后像这样运行任务:

your_arg = 3

custom_task = CustomTask()
custom_task.delay(your_arg)

I am not sure if ignore_result = True part is necessary or not.我不确定ignore_result = True部分是否必要。

When you have:当你有:

    a = A()

you can do:你可以做:

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

Cheers干杯

For me the only one that works is celery.current_app because just this passes self to the method.对我来说,唯一有效的方法是 celery.current_app,因为这将self传递给方法。

So this should look like this:所以这应该是这样的:

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

The name must be used if you have method with the same name in different classes.如果您在不同的类中具有相同名称的方法,则必须使用该名称。

I ran into a similar situation and decided to wrap class methods within a simple function that would redirect its parameters to an instance of the class and it's execution of such methods:我遇到了类似的情况,并决定将类方法包装在一个简单的函数中,该函数会将其参数重定向到类的实例,并执行此类方法:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM