从并行Celery任务执行中收集结果

时间:2015-12-14 21:09:09

标签: python celery celery-task

我正在尝试实现一个相当简单的Celery工作流,​​在那里我收到与元组(或列表)相同任务的多个并行调用的结果。

@app.task
def add(x, y):
    return x + y

@app.task
def master():
    return group(add.s(1, 2), add.s(3, 4))()

由此,我想以通用的方式检索(3, 7) ,即以不依赖于工作流本身的方式。我正在寻找某种“将异步结果图缩减为基元”操作。我已经尝试了以下内容(为简洁起见,我已将结果ID替换为#num

r = master.delay()
r.get()      # <GroupResult: #1 [#2, #3]>
r.collect()  # [(<AsyncResult: #0>, <GroupResult #1 [#2, #3]>),
             #  (<GroupResult: #1 [#2, #3]>, [3, 7])
             #  (<AsyncResult: #2>, 3),
             #  (<GroupResult: #3>, 7)]

r.get()返回两个AsyncResult ID的包装器,因此我必须递归处理每个ID。 r.collect()已接近尾声,但它过于深入。

我可以做类似

的事情
r.children[0].get()

但这不是通用的,因为它明确取决于结果图的结构。此外,我可以遍历r.collect(),直到我找到一个元组,其值不是ResultBase的实例,如

next(value for _, value in r.collect() if not isinstance(value, ResultBase))

但我不确定这在所有情况下是否真的都是正确的,我希望有更优雅的方法来做到这一点。

如果有一种方法可以重构master任务以便更轻松地检索结果,那么只要子任务并行启动,我就会对此持开放态度。任何建议,将不胜感激。提前谢谢。

编辑相关问题是,如果我想以非阻止方式检索任务结果(例如,在调用r.status之前手动轮询r.get()r.collect(),我不能简单地这样做

r = master.delay()

# some time later...
if r.status in READY_STATES:
    r.get()

因为rAsyncResult,它解析为GroupResult,即它在GroupResult或其子项之前完成。有没有办法以“跳过”顶级AsyncResult的方式调用该组?这将解决这两个问题,因为r.statusr.get()将分别反映子任务的状态和值。

1 个答案:

答案 0 :(得分:1)

当然,正确的解决方案是最简单的解决方案:调用r = master() r.get() # [3, 7] r.collect() # [(<GroupResult: #1 [#2, #3]>, [3, 7]), # (<AsyncResult: #2>, 3), # (<AsyncResult: #3>, 7)] 作为在当前进程中执行它的函数。

group

不是将group启动代码推迟到工作进程,而是在当前进程中启动。由于\\test01\file1.pdf \\test08\file8.pdf etc. 完全是异步的,因此行为不会改变,性能也会提高。