我正在使用Celery来执行非常长的任务(多个小时),并希望能够杀死个别任务。
如果我没有弄错,这是优雅地终止任务的正确方法:
task = long_task.AsyncResult(task_id)
task.revoke(terminate=True)
我的任务如下:
@celery.task(bind=True, throws=(Terminated,))
def long_task(self):
try:
... do all kinds of things ...
except Terminated:
print("Task was terminated")
except:
print("Unknown exception!")
我第一次终止任务时会打印出#34;未知异常!"在控制台上,因此引发异常并在任务中捕获,但不知何故不是Terminated异常。我不明白为什么它没有捕获终止的例外。
我导入了Terminated异常,如下所示:
from billiard.exceptions import Terminated
但事情真的很奇怪,每次我终止一个SECOND任务时,控制台都会给我一个ERROR / MainProcess任务处理程序引发的错误:终止(15,)。我认为正在发生的事情是,这次任务不会引发异常,但工人会这样做。
我想我可以在异常处理程序中包装task.revoke(),但是重点是什么 - 为什么task.revoke()会像这样引发异常?
顺便说一下,任何第三个任务都像第一个任务一样,第四个任务就像第二个任务一样,等等。因此它在任务中不一致,但始终不一致'。
有什么建议吗?
使用Celery 4.1.0,Python 3.5.2和Redis 4.0.7。
答案 0 :(得分:0)
我遇到了同样的问题,但我使用的是 celery v4.4.0 和 python 3.7
我发现尽管错误消息说明了以下内容
Task handler raised error: Terminated(15)
Traceback (most recent call last):
File "[...]/pool.py", line 1728, in _set_terminated
raise Terminated(-(signum or 0))
billiard.exceptions.Terminated: 15
这显然是 just a log message 并且实际上引发了 SystemExit 异常。需要注意的是 SystemExit 不是从 Exception 继承的,所以你需要专门用 SystemExit 来捕获它
try:
...
except SystemExit as e:
...
我的完整工作示例如下,它似乎无需在任务定义中指定异常即可工作。
@app.task()
def long_task():
try:
... do the long thing ...
except SystemExit:
print("Task was stopped manually")
except:
print("Some other error occured during task execution")
raise