Celery Django 运行 task 任务的时候 提示 NotRegistered
原来引入task 的方式是
1
2
|
from
app01
.
utils
.
tasks
import
*
|
但是老是提示 xxxtask NotRegistered,查询了好多的资料,终于解决了
因为是 Django 项目,所以在Celey 中需要引入制定的 task, 有人说 app.autodiscover_tasks()
可以自动导入,但是还是报错说 xxxtask 未被注册
方法一
所以我采用导入指定的 task 的方式:
1
2
3
4
5
|
CELERY_IMPORTS
=
(
# 指定导入的任务模块
'celery_app.task1'
,
'celery_app.task2'
)
|
然后就不会报错了 : )
方法二
在 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"形式的名字:
1
2
|
INSTALLED_APPS
=
[
'project.myapp'
]
|
如果你的app安装在project.myapp下,这样你的tasks模块将会以"project.myapp.tasks"形式导入,所以你必须保证总是以同样的名字导入tasks:
1
2
3
4
|
>>>
from
project
.
myapp
.
tasks
import
mytask
# << GOOD
>>>
from
myapp
.
tasks
import
mytask
# << BAD!!!
|
下面是第二个例子,client和worker以不同的名称导入了tasks模块进而造成了task被命名为不同的名字:
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中也是一个好的实践。
相似地,你不要使用老的相对导入方式:
1
2
3
4
|
from
module
import
foo
# BAD!
from
proj
.
module
import
foo
# GOOD!
|
新的相对导入方式是可以的:
1
2
|
from
.
module
import
foo
# GOOD!
|
如果你正在使用的Celery工程中已经广泛使用了这样的导入方式,你也没有时间重构这些代码,那么你可以考虑显式地指定任务的名称而不是依赖于自动命名:
1
2
3
4
|
@
task
(
name
=
'proj.tasks.add'
)
def
add
(
x
,
y
)
:
return
x
+
y
|