Python 如何将 @shared_task 装饰器用于基于类的任务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21233089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use the @shared_task decorator for class based tasks
提问by Juan Riaza
As seen on the documentationthe @shared_taskdecorator lets you create tasks without having any concrete app instance. The given examples shows how to decorate a function based task.
由于上看到文档的@shared_task装饰让你无需任何具体的应用程序实例创建任务。给定的示例展示了如何装饰基于函数的任务。
How to decorate a class based task?
如何装饰基于类的任务?
采纳答案by Saurabh
Quoting Ask from celery-users thread where he explained difference between @task a @shared_task. Here is link to the thread
引用 celery-users 线程中的 Ask,他解释了 @task 和 @shared_task 之间的区别。这是线程的链接
TL;DR; @shared_task will create the independent instance of the task for each app, making task reusable.
TL; 博士; @shared_task 将为每个应用程序创建独立的任务实例,使任务可重用。
There is a difference between @task(shared=True) and @shared_task
@task(shared=True) 和@shared_task 之间有区别
The task decorator will share tasks between apps by default so that if you do:
默认情况下,任务装饰器将在应用程序之间共享任务,因此如果您这样做:
app1 = Celery()
@app1.task
def test():
pass
app2 = Celery()
the test task will be registered in both apps:
测试任务将在两个应用程序中注册:
assert app1.tasks[test.name]
assert app2.tasks[test.name]
However, the name ‘test' will always refer to the instance bound to the ‘app1' app, so it will be configured using app1's configuration:
但是,名称“test”将始终引用绑定到“app1”应用程序的实例,因此将使用 app1 的配置对其进行配置:
assert test.app is app1
The @shared_task decorator returns a proxy that always uses the task instance in the current_app:
@shared_task 装饰器返回一个始终使用 current_app 中的任务实例的代理:
app1 = Celery()
@shared_task
def test():
pass
assert test.app is app1
app2 = Celery()
assert test.app is app2
This makes the @shared_task decorator useful for libraries and reusable apps, since they will not have access to the app of the user.
这使得 @shared_task 装饰器对库和可重用应用程序很有用,因为它们将无法访问用户的应用程序。
In addition the default Django example project defines the app instance as part of the Django project:
此外,默认的 Django 示例项目将应用程序实例定义为 Django 项目的一部分:
from proj.celery import app
从 proj.celery 导入应用程序
and it makes no sense for a Django reusable app to depend on the project module, as then it would not be reusable anymore.
并且 Django 可重用应用程序依赖于项目模块是没有意义的,因为那样它将不再可重用。
回答by jdhildeb
The documentation you linked to says:
您链接到的文档说:
The @shared_task decorator lets you create tasks without having any concrete app instance:
@shared_task 装饰器使您无需任何具体的应用程序实例即可创建任务:
As far as I can tell, the documentation is misleading, and should say:
据我所知,文档具有误导性,应该说:
The @shared_task decorator lets you create tasks that can be used by any app(s).
@shared_task 装饰器可让您创建可由任何应用程序使用的任务。
In fact, any Task must be attached to an app instance. My evidence comes from the celery source file celery/app/builtins.py:
实际上,任何任务都必须附加到应用程序实例。我的证据来自芹菜源文件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
So it lookslike you can use this decorator to create a task without having a concrete app instance, but in fact the decorated function MUST take an app argument - as the source comment says.
所以看起来你可以使用这个装饰器来创建一个没有具体应用程序实例的任务,但实际上被装饰的函数必须接受一个应用程序参数 - 正如源评论所说。
The next function follows:
下一个函数如下:
def load_shared_tasks(app):
"""Create built-in tasks for an app instance."""
constructors = set(_shared_tasks)
for constructor in constructors:
constructor(app)
You can confirm here that each function decorated by @shared_taskswillbe invoked with an appargument.
您可以在此处确认每个装饰的函数@shared_tasks都将使用app参数调用。

