在Celery文档中:http://celery.readthedocs.org/en/latest/userguide/canvas.html#chains是如何使用link_error
:
您还可以使用link_error参数添加错误回调:
add.apply_async((2, 2), link_error=log_error.s()) add.subtask((2, 2), link_error=log_error.s())
由于异常只能在使用pickle时序列化错误 回调将父任务的id作为参数:
from __future__ import print_function import os from proj.celery import app @app.task def log_error(task_id): result = app.AsyncResult(task_id) result.get(propagate=False) # make sure result written. with open(os.path.join('/var/errors', task_id), 'a') as fh: print('--\n\n{0} {1} {2}'.format( task_id, result.result, result.traceback), file=fh)
但是在这个例子中是bug,因为他们在任务中调用AsuncResult.get
导致DEADLOCK
和这个日志条目:
/opt/.virtualenvs/spark/lib/python3.4/site-packages/celery/result.py:45: RuntimeWarning: Never call result.get() within a task!
See http://docs.celeryq.org/en/latest/userguide/tasks.html#task-synchronous-subtasks
In Celery 3.2 this will result in an exception being
raised instead of just being a warning.
warnings.warn(RuntimeWarning(E_WOULDBLOCK))
[2015-06-13 20:30:19,242: WARNING/Worker-4] /opt/.virtualenvs/spark/lib/python3.4/site-packages/celery/result.py:45: RuntimeWarning: Never call result.get() within a task!
See http://docs.celeryq.org/en/latest/userguide/tasks.html#task-synchronous-subtasks
In Celery 3.2 this will result in an exception being
raised instead of just being a warning.
warnings.warn(RuntimeWarning(E_WOULDBLOCK))
答案 0 :(得分:0)
请执行此检查列表以确保配置正常:
CELERY_IGNORE_RESULT
必须设为False
CELERY_BACKEND_RESULT
,例如'amqp'
(对于RabbitMQ)@task
装饰者必须选项ignore_result=True
(但您可以创建immutable signatures)最后一个是正确修改的任务,用于获取结果(allow_join_result):
from celery.result import allow_join_result
@app.task
def log_error(task_id):
with allow_join_result():
result = app.AsyncResult(task_id)
result.get(propagate=False) # make sure result written.
with open(os.path.join('/var/errors', task_id), 'a') as fh:
print('--\n\n{0} {1} {2}'.format(
task_id, result.result, result.traceback), file=fh)
注意:强>
在这种result.result
的情况下,ZeroDivisionError
是字典:
{
'exc_type': 'ZeroDivisionError', # Name of Exception type
'exc_message': 'division by zero' # Reason of exception
}
这是#2652问题,当Celery忽略错误时在get()
上调用AsyncResult