Celery Django 运行 task 任务的时候 提示 NotRegistered
原来引入task 的方式是
Python
from app01.utils.tasks import *
1 2 | from app01 . utils . tasks import * |
但是老是提示 xxxtask NotRegistered,查询了好多的资料,终于解决了
因为是 Django 项目,所以在Celey 中需要引入制定的 task, 有人说 app.autodiscover_tasks() 可以自动导入,但是还是报错说 xxxtask 未被注册
方法一
所以我采用导入指定的 task 的方式:
Python
CELERY_IMPORTS = ( # 指定导入的任务模块 'celery_app.task1', 'celery_app.task2' )
1 2 3 4 5 | CELERY_IMPORTS = ( # 指定导入的任务模块 'celery_app.task1' , 'celery_app.task2' ) |
然后就不会报错了 : )
方法二
在 task 文件中 加入
Python
from __future__ import absolute_import, unicode_literals from celery import shared_task
1 2 3 | from __future__ import absolute_import , unicode_literals from celery import shared _task |
使用绝对了路径进行导入
找到相关的原因了,是相对路径和绝对路径的问题
自动命名和相对导入
"相对导入"和"自动名称生成"在一起工作的不是很好,所以如果你使用了"相对导入",就需要显式地指明名字。
比如,如果客户端导入模块"myapp.tasks"作为".tasks",然后worker导入模块作为“myapp.tasks”,这样自动生成的名字就不能够正确匹配,worker就会抛出一个 NotRegistered
异常。
同样的情况在Django中也会发生,当你在INSTALLED_APPS中使用了"project.myapp"形式的名字:
Python
INSTALLED_APPS = ['project.myapp']
1 2 | INSTALLED_APPS = [ 'project.myapp' ] |
如果你的app安装在project.myapp下,这样你的tasks模块将会以"project.myapp.tasks"形式导入,所以你必须保证总是以同样的名字导入tasks:
Python
>>> from project.myapp.tasks import mytask # << GOOD >>> from myapp.tasks import mytask # << BAD!!!
1 2 3 4 | >>> from project . myapp . tasks import mytask # << GOOD >>> from myapp . tasks import mytask # << BAD!!! |
下面是第二个例子,client和worker以不同的名称导入了tasks模块进而造成了task被命名为不同的名字:
Python
>>> from project.myapp.tasks import mytask >>> mytask.name 'project.myapp.tasks.mytask' >>> from myapp.tasks import mytask >>> mytask.name 'myapp.tasks.mytask'
1 2 3 4 5 6 7 8 | >>> from project . myapp . tasks import mytask >>> mytask . name 'project.myapp.tasks.mytask' >>> from myapp . tasks import mytask >>> mytask . name 'myapp.tasks.mytask' |
基于以上原因,你必须以相同的方式导入模块,这在python中也是一个好的实践。
相似地,你不要使用老的相对导入方式:
Python
from module import foo # BAD! from proj.module import foo # GOOD!
1 2 3 4 | from module import foo # BAD! from proj . module import foo # GOOD! |
新的相对导入方式是可以的:
Python
from .module import foo # GOOD!
1 2 | from . module import foo # GOOD! |
如果你正在使用的Celery工程中已经广泛使用了这样的导入方式,你也没有时间重构这些代码,那么你可以考虑显式地指定任务的名称而不是依赖于自动命名:
Python
@task(name='proj.tasks.add') def add(x, y): return x + y
1 2 3 4 | @ task ( name = 'proj.tasks.add' ) def add ( x , y ) : return x + y |
版权声明:本文为songhao8080原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。