我拼命想让Celery和Django打得好,但没有成功。我被以下问题绊倒了:
项目/设置.py:
...
import djcelery
djcelery.setup_loader()
BROKER_URL = 'django://'
CELERY_RESULT_BACKEND = 'django://'
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_ENABLE_UTC = True
...
app/tasks.py:
from celery.task import task
@task()
def scheduled_task(param1, param2):
...
return something
直接调用scheduled_task(param1, param2)
(不使用decorator)可以按预期工作。然而,当添加装饰师并像这样激发"开发"芹菜工人时:
python manage.py celery worker --loglevel=info
我得到以下错误:
TypeError: 'module' object is not callable
我已经把它固定在@task
装饰器上了。我尝试的每个组合都失败了,包括:
from celery import task
from celery.task import task
from celery.task.base import task
@task
@task()
@task.task
@task.task()
@celery.task
@celery.task()
异常中的调用堆栈似乎没有任何区别,它们都出现,认为task
是一个模块,不可调用!让事情变得更加令人沮丧:
>>> from celery.task import task
>>> task
<function task at 0x10aa2a758>
在我看来,那真是太好了!知道可能会发生什么吗?如果我遗漏了什么,我很乐意发布额外的日志、文件或澄清任何其他内容。
以防万一有人正在使用Celery beat并收到相同的错误消息。在我的应用程序中,我使用了
command=/opt/python/run/venv/bin/celery beat -A appname --loglevel=INFO --workdir=/tmp -S django --pidfile /tmp/celerybeat.pid
并收到此错误消息。由于我使用supervisord复制了用于守护Celery beat的大部分代码(您需要对此进行特殊配置),所以我没有意识到"-S django"假定使用django_seley_beat包,而我以前没有安装过该包。我安装它是因为它无论如何都有生产使用的优势,并且错误消失了。
(从注释转换为答案)
根据堆栈跟踪,我认为return backend(app=self, url=url)
行是异常发生的地方。
所以不管backend
是什么,它似乎都不是可调用的。我会尝试通过在中包装该行来在该文件(celery/app/base.py
)中设置一个pdb断点
try:
backend(app=self, url=url)
except:
import pdb; pdb.set_trace(),
然后检查backend
,并向上移动堆栈(pdb中的u
命令,d
再次向下,w
显示调用堆栈),以调试所有出错的地方。
芹菜文档也提到了这一点:
如何导入任务装饰器
任务装饰器在您的Celery实例上可用,如果您不知道它是什么,请阅读Celery的第一步。
如果您正在使用Django,或者仍在使用基于"旧"模块的celele API,那么您可以导入任务装饰器,如下所示:
from celery import task
@task
def add(x, y):
return x + y
因此,这应该可以消除关于导入任务装饰器的正确方式的任何歧义。
这是一个有点老的问题,但我遇到了类似的麻烦,这对我很有效:
项目/设置.py:
...
import djcelery
djcelery.setup_loader()
BROKER_URL = 'django://'
CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_ENABLE_UTC = True
...