我有完全相同的愿望。在运行作业之前生成图形。所以我做了一些工作:)
看来celery不允许。这样做的原因(至少我在尝试这样做时理解的是)是在图中每个节点都必须有一个唯一的名称。一旦 Canvas 被执行,这个唯一的名称就是 celery task_id 但在执行之前没有任何东西允许这样的区别。
所以解决方案是自己生成这个图,当然还要唯一地标识每个节点(为此,计数器可以完成工作)。
这是这个函数的工作:
# -*- coding: utf-8 -*-
from celery.canvas import chain, group, Signature
def analyze_canvas(canvas):
return _analyze_canvas(canvas)['dependencies']
def _analyze_canvas(canvas, previous=[], i=0):
dependencies = []
if isinstance(canvas, chain):
for t in canvas.tasks:
if not (isinstance(t, group) or isinstance(t, chain)):
n = str(t) + " - (" + str(i) + ")"
i += 1
dependencies.append((n, previous))
previous = [n]
else:
analysis = _analyze_canvas(t, previous, i)
dependencies.extend(analysis['dependencies'])
previous = analysis['previous']
elif isinstance(canvas, group):
new_previous = []
for t in canvas.tasks:
if not (isinstance(t, group) or isinstance(t, chain)):
n = str(t) + " - (" + str(i) + ")"
i += 1
dependencies.append((n, previous))
new_previous.append(n)
else:
analysis = _analyze_canvas(t, previous, i)
dependencies.extend(analysis['dependencies'])
new_previous = analysis['previous']
previous = new_previous
elif isinstance(canvas, Signature):
n = str(t) + " - (" + str(i) + ")"
i += 1
dependencies.append((n, previous))
previous = [n]
return {"dependencies": dependencies,
"previous": previous}
它生成 Canvas 的依赖关系图。这个想法只是迭代 Canvas 的其他任务并识别组/链/签名以生成正确的依赖项。
从这一点开始,您可以使用更多的 celery utils 来生成点文件。这是一个小的用法示例:
from celery_util import analyze_canvas
from celery.datastructures import DependencyGraph
from celery import Celery, group
app = Celery()
@app.task
def t1():
pass
@app.task
def t2():
pass
canvas = t1.si() | t2.si() | group(t1.si(), t1.si(), t2.si()) | t2.si()
d = analyze_canvas(canvas)
dg = DependencyGraph(it=d)
pipo = open("pipo.dot", "w+")
dg.to_dot(pipo)
在这个例子中,我只是声明了虚拟任务并将它们链接/分组在一个漂亮的 Canvas 中。我使用 celery util DependencyGraph
来获得对象表示和将图形转储到点中的能力,这是我使用 to_dot
方法完成的。
漂亮的结果是:
我是一名优秀的程序员,十分优秀!