Celery似乎没有正确处理异常。
如果我有任务:
def errorTest():
raise Exception()
然后我打电话
r = errorTest.delay()
In [8]: r.result
In [9]: r.state
Out[9]: 'PENDING'
它会无限期地挂起来。
去检查日志显示错误被抛出任务(如果你想要消息,请问),我知道后端和一切都设置正确,因为其他任务正常工作并正确返回结果。
在Celery中捕获异常需要做些什么时髦吗?
/ Celery版本是3.0.13,经纪人是在我的本地机器上运行的RabbitMQ
答案 0 :(得分:29)
如果您在CELERY_ALWAYS_EAGER设置为True的情况下运行Celery,请确保在您的设置中也包含此行:
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
http://docs.celeryproject.org/en/latest/configuration.html#celery-eager-propagates-exceptions
答案 1 :(得分:13)
您可以在Task
子类中定义on_failure
函数来正确处理它们。如果您只是想知道发生了什么,可以设置error email notifications,它会在您的芹菜配置中向您发送堆栈跟踪。
注意:截至v4 Celery no longer supports sending emails。
答案 2 :(得分:3)
让@ primalpython的答案更明确。
这将失败:
@task
def error():
raise Exception
输入/输出:
In [7]: r = error.delay()
In [8]: print r.state
Out[8]: 'PENDING'
In [9]: print r.result
Out[9]: None
这将成功:
@task
def error():
raise Exception
def on_failure(self, *args, **kwargs):
pass
输入/输出:
In [7]: r = error.delay()
In [8]: print r.state
Out[8]: 'FAILURE'
In [9]: print r.result
Out[9]: Exception()
答案 3 :(得分:1)
IMO最简单的方法是传入对创建新Celery应用程序时要使用的任务类的引用。
在一个模块中,定义默认使用的任务类:
from celery.app.task import Task
import logging
logger=logging.getLogger(__name__)
class LoggingTask(Task):
def on_failure(self, exc, task_id, args, kwargs, einfo):
kwargs={}
if logger.isEnabledFor(logging.DEBUG):
kwargs['exc_info']=exc
logger.error('Task % failed to execute', task_id, **kwargs)
super().on_failure(exc, task_id, args, kwargs, einfo)
定义应用程序时,请引用模块(注意,这是您提供的字符串引用。):
from celery import Celery
app=Celery('my_project_name', task_cls='task_package.module_name:LoggingTask')
从那时起,如果未专门提供任何任务类,则将使用LoggingTask-从而使您可以实现所有个现有任务(使用默认任务),而不必修改每个任务。这也意味着您可以正常使用@shared_task装饰器。