如何使用@shared_task装饰器进行基于类的任务

时间:2014-01-20 11:40:36

标签: python celery

documentation所示,@shared_task装饰器可让您在没有任何具体应用实例的情况下创建任务。给出的示例显示了如何装饰基于函数的任务。

如何装饰基于类的任务?

2 个答案:

答案 0 :(得分:14)

从celery-users线程中引用提问,他解释了@task与@shared_task之间的区别。 Here is link to the thread

TL; DR; @shared_task将为每个应用程序创建任务的独立实例,使任务可重用。

@task(shared = True)和@shared_task

之间存在差异

默认情况下,任务装饰器将在应用程序之间共享任务,以便执行以下操作:

app1 = Celery() 
@app1.task 
def test(): 
    pass 

app2 = Celery() 

测试任务将在两个应用程序中注册:

 assert app1.tasks[test.name] 
 assert app2.tasks[test.name] 

但是,名称'test'将始终引用绑定到'app1'的实例 应用程序,因此将使用app1的配置进行配置:

assert test.app is app1 

@shared_task装饰器返回一个始终使用任务实例的代理 在current_app中:

app1 = Celery() 

@shared_task 
def test(): 
    pass 
assert test.app is app1 


app2 = Celery() 
assert test.app is app2 

这使得@shared_task装饰器对库和可重用的应用程序很有用, 因为他们无法访问用户的应用程序。

此外,默认的Django示例项目定义了app实例 作为Django项目的一部分:

来自proj.celery导入应用

并且Django可重用应用依赖于项目模块没有意义, 因为那时它不再可以重复使用了。

答案 1 :(得分:9)

您链接的文档说:

  

@shared_task装饰器允许您创建任务而无需任何具体的应用程序实例:

据我所知,文档具有误导性,应该说:

  

@shared_task装饰器可让您创建任何应用程序都可以使用的任务。

实际上,任何Task都必须附加到app实例。我的证据来自芹菜源文件celery/app/builtins.py

def shared_task(constructor):
    """Decorator that specifies a function that generates a built-in task.

    The function will then be called for every new app instance created
    (lazily, so more exactly when the task registry for that app is needed).

    The function must take a single ``app`` argument.
    """
    _shared_tasks.add(constructor)
    return constructor

所以它看起来就像你可以使用这个装饰器来创建一个没有具体应用实例的任务,但实际上装饰的函数必须采用一个app参数 - 正如源评论所说。

下一个功能如下:

def load_shared_tasks(app):
    """Create built-in tasks for an app instance."""
    constructors = set(_shared_tasks)
    for constructor in constructors:
        constructor(app)

您可以在此确认使用@shared_tasks参数调用由app 修饰的每个函数