我正在尝试实现一个相当简单的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()
因为r
是AsyncResult
,它解析为GroupResult
,即它在GroupResult
或其子项之前完成。有没有办法以“跳过”顶级AsyncResult
的方式调用该组?这将解决这两个问题,因为r.status
和r.get()
将分别反映子任务的状态和值。
答案 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.
完全是异步的,因此行为不会改变,性能也会提高。