Skip to main content
 首页 » 编程设计

python之运行前绘制 Celery canvas

2025年05月04日8lautakyan007

关于 how to produce a graph after running a canvas job 的文档在 celery 中。 但是,我想在运行该作业之前生成一个图表。

假设我创建了一个简单的链:

c = chain(add.s(1, 2), mul(4)) 

如何生成链图?

谢谢,

三木

请您参考如下方法:

我有完全相同的愿望。在运行作业之前生成图形。所以我做了一些工作:)

看来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 方法完成的。

漂亮的结果是: