Python 在完成所有任务后运行任务
我正在编写一个应用程序,它需要并行运行一系列任务,然后运行一个包含所有任务运行结果的单个任务:Python 在完成所有任务后运行任务,python,rabbitmq,celery,Python,Rabbitmq,Celery,我正在编写一个应用程序,它需要并行运行一系列任务,然后运行一个包含所有任务运行结果的单个任务: @celery.task def power(value, expo): return value ** expo @celery.task def amass(values): print str(values) 这是一个非常做作和过于简单的例子,但希望这一点能得到很好的理解。基本上,我有许多项目需要运行power,但我只想对所有任务的结果运行amass。所有这些都应该异步进行,
@celery.task
def power(value, expo):
return value ** expo
@celery.task
def amass(values):
print str(values)
这是一个非常做作和过于简单的例子,但希望这一点能得到很好的理解。基本上,我有许多项目需要运行power
,但我只想对所有任务的结果运行amass
。所有这些都应该异步进行,我不需要从amass
方法返回任何内容
有人知道如何在芹菜中设置它,以便异步执行所有操作,并在所有操作完成后调用带有结果列表的单个回调吗
我已将此示例设置为按照Alexander Afanasiev的建议使用和弦运行:
from time import sleep
import random
tasks = []
for i in xrange(10):
tasks.append(power.s((i, 2)))
sleep(random.randint(10, 1000) / 1000.0) # sleep for 10-1000ms
callback = amass.s()
r = chord(tasks)(callback)
不幸的是,在上面的示例中,tasks
中的所有任务只有在调用chord
方法时才会启动。是否有一种方法可以让每个任务单独启动,然后我可以向组中添加一个回调,以便在完成所有任务后运行?芹菜可以为您想象的大多数工作流提供支持
看来你需要好好利用一下。以下是docs的报价:
和弦就像一个组,但有回调。和弦包括
标题组和正文,其中正文是应
在标头中的所有任务完成后执行
@alexander afanasiev给你的答案基本上是正确的:使用和弦
您的代码还可以,但是tasks.append(power.s((i,2))
实际上并没有执行子任务,只是添加到列表中。它是chord(…)(…)
向代理发送的消息数量与您在tasks
列表中定义的子任务数量相同,另外还有一条消息用于回调子任务。当您调用chord
时,它会尽快返回
如果您想知道和弦何时完成,您可以像使用示例中的r.ready()
一样使用单个任务来轮询完成情况。以下是一个适合我的解决方案:
任务。py:
from time import sleep
import random
@celery.task
def power(value, expo):
sleep(random.randint(10, 1000) / 1000.0) # sleep for 10-1000ms
return value ** expo
@celery.task
def amass(results, tasks):
completed_tasks = []
for task in tasks:
if task.ready():
completed_tasks.append(task)
results.append(task.get())
# remove completed tasks
tasks = list(set(tasks) - set(completed_tasks))
if len(tasks) > 0:
# resend the task to execute at least 1 second from now
amass.delay(results, tasks, countdown=1)
else:
# we done
print results
用例:
tasks = []
for i in xrange(10):
tasks.append(power.delay(i, 2))
amass.delay([], tasks)
这应该做的是尽快异步启动所有任务。一旦它们都被发布到队列中,amass
任务也将被发布到队列中。在所有其他任务完成之前,聚合任务将继续重新发布自身 看看你问题中的这个片段,它看起来像是在传递一个列表
作为和弦标题,而不是一个组
:
from time import sleep
import random
tasks = []
for i in xrange(10):
tasks.append(power.s((i, 2)))
sleep(random.randint(10, 1000) / 1000.0) # sleep for 10-1000ms
callback = amass.s()
r = chord(tasks)(callback)
将列表
转换为组
会导致您预期的行为:
...
callback = amass.s()
tasks = group(tasks)
r = chord(tasks)(callback)
这是绝对正确的,但是,它有一个问题。我已经用细节更新了我的答案。我希望每个子任务在发布后立即执行,而不是在发布和弦时执行。这可能吗?好吧,在循环中执行一个power.delay(i,2)
,在调用amass(results)
之前轮询所有中间结果以完成。但我真的不明白重点。使用chord将在代理中的power.s
子任务作为消息提供后立即执行,并在完成后执行amass
。我认为你应该明确你想要实现什么,因为您异步执行任务的愿望似乎与您建议的用法相矛盾。我提出了一个解决方案,上面演示了我想做的事情。我想您刚刚重新实现了chord
函数。一点也不:我想您不明白我的要求。chord函数在被调用之前不会开始执行任务。然而,在我的代码中,任务立即开始执行,然后完成处理程序也被发布到队列中。在我的用例中,我不会调用实际的chord函数,直到将来的某个时候,我已经开始了工作的所有必要任务。从本质上讲,chord函数是惰性的,只有当任务都被发布并且chord函数被调用时才开始执行任务。我的实现非常迫切,因为它会尽快启动所有任务。嗨,看起来上面的方法是一个很好的方法,至少在概念上是这样。但是,当我尝试使用与上面完全相同的代码时,它抛出了以下错误:encoderror:is not JSON serializable
非常感谢您的帮助。好的,我通过传递最后的_任务()解决了上面的错误TaskID列表本身直接传递,而不是像上面的代码示例中那样传递任务对象列表。无论如何,谢谢你的回答。这帮了大忙。投票!如果每个小组开始一项新任务,你想让和弦说等待每个小组的子任务完成,那么你知道这是如何工作的吗?或者,我已经有一段时间没有详细研究芹菜了,所以我不知道4.x是如何工作的