我希望Celery的任务取决于2个或更多其他任务的结果。我查看了Python+Celery: Chaining jobs?和http://pypi.python.org/pypi/celery-tasktree,但只有当任务只有一个相关任务时,这些才有用。
我了解TaskSet,但是当TaskSetResult.ready()变为True时,似乎没有办法立即执行回调。我现在想到的是有一个周期性的任务,每隔几[毫秒]左右轮询一次TaskSetResult.ready()并在返回True时触发回调,但这对我来说听起来相当不优雅。
有什么建议吗?
答案 0 :(得分:9)
在Celery(3.0+)的最新版本中,你可以使用所谓的和弦来达到预期的效果:
来自http://docs.celeryproject.org/en/latest/userguide/canvas.html#the-primitives:
简单的和弦
chord原语使我们能够添加回调以便在所有时调用 组中的任务已经完成执行,这通常是 算法并不是令人尴尬地并行:
>>> from celery import chord
>>> res = chord((add.s(i, i) for i in xrange(10)), xsum.s())()
>>> res.get()
90
免责声明:我自己还没试过。
答案 1 :(得分:3)
mrbox是真的,你可以重试直到结果准备就绪,但是在文档中不太清楚,当你重试时你必须传递setid和子任务元素,并且为了恢复它你必须使用map函数,下面有一个示例代码,用于解释我的意思。
def run(self, setid=None, subtasks=None, **kwargs):
if not setid or not subtasks:
#Is the first time that I launch this task, I'm going to launch the subtasks
…
tasks = []
for slice in slices:
tasks.append(uploadTrackSlice.subtask((slice,folder_name)))
job = TaskSet(tasks=tasks)
task_set_result = job.apply_async()
setid = task_set_result.taskset_id
subtasks = [result.task_id for result in task_set_result.subtasks]
self.retry(exc=Exception("Result not ready"), args=[setid,subtasks])
#Is a retry than we just have to check the results
tasks_result = TaskSetResult(setid, map(AsyncResult,subtasks))
if not tasks_result.ready():
self.retry(exc=Exception("Result not ready"), args=[setid,subtasks])
else:
if tasks_result.successful():
return tasks_result.join()
else:
raise Exception("Some of the tasks was failing")
答案 2 :(得分:2)
恕我直言,你可以做类似于docs- link
中完成的事情或者你可以使用max_retries = None的重试方法 - 如果其中一个'基本'任务.ready()为false,你可以触发.retry()方法直到两个'基础'任务完成。