克隆芹菜链

时间:2018-11-14 06:42:20

标签: celery python-3.6 celery-canvas

我有一个有趣的问题,试图克隆一个芹菜链供小组使用,我的预期用例类似于group([chain.clone(args=args) for args in it]),但它一直抱怨没有足够的论据。

我已使用以下内容对此进行了细分

在名为tasks.py的文件中

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

然后在python shell中

>>> from tasks import add
>>> chain=add.s()|add.s(1)
>>> chain
magic_carpet.celery.add() | add(1)
>>> chain.args
()
>>> chain.delay(2,2)
<AsyncResult: fcc97c30-4700-47a6-aeb6-ffca19a1446f>
>>> cloned_chain=chain.clone(args=(2,))
>>> cloned_chain.args
()
>>> cloned_chain.delay(2)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/bjorn/.local/share/virtualenvs/magic_carpet-PeFVEcL-/lib/python3.6/site-packages/celery/canvas.py", line 179, in delay
    return self.apply_async(partial_args, partial_kwargs)
  File "/home/bjorn/.local/share/virtualenvs/magic_carpet-PeFVEcL-/lib/python3.6/site-packages/celery/canvas.py", line 557, in apply_async
    dict(self.options, **options) if options else self.options))
  File "/home/bjorn/.local/share/virtualenvs/magic_carpet-PeFVEcL-/lib/python3.6/site-packages/celery/canvas.py", line 584, in run
    first_task.apply_async(**options)
  File "/home/bjorn/.local/share/virtualenvs/magic_carpet-PeFVEcL-/lib/python3.6/site-packages/celery/canvas.py", line 218, in apply_async
    return _apply(args, kwargs, **options)
  File "/home/bjorn/.local/share/virtualenvs/magic_carpet-PeFVEcL-/lib/python3.6/site-packages/celery/app/task.py", line 513, in apply_async
    check_arguments(*(args or ()), **(kwargs or {}))
TypeError: add() missing 1 required positional argument: 'y'
>>> 

很显然,clone并没有取代链的克隆副本中的args,但是我不确定为什么_chain类的克隆方法实现为

>>> from celery.canvas import _chain
>>> help(_chain.clone)

Help on function clone in module celery.canvas:

clone(self, *args, **kwargs)
    Create a copy of this signature.

    Arguments:
        args (Tuple): Partial args to be prepended to the existing args.
        kwargs (Dict): Partial kwargs to be merged with existing kwargs.
        options (Dict): Partial options to be merged with
            existing options.

阅读芹菜来源,我看不出会导致这种情况的任何明显原因。

当前正在运行Celery 4.2.1和Python 3.6.6

此功能是否因某种原因而被破坏,不受支持,或者我是难以置信的钝器并且做错了什么事?

1 个答案:

答案 0 :(得分:0)

因此,事实证明,核心问题是通过回旋过程,clone调用构造函数进行链式创建新实例。此构造函数不接受任何应用于该链的args或kwargs,而是将它们默认为空值,从而导致它们丢失。

目前,我的解决方案是通过创建自己的克隆方法(该方法修改链中第一个任务的参数)来解决此问题。设置args属性时似乎也可以使用,如果再次在芹菜中克隆该链时,存储在其中的值将丢失。

我的克隆方法目前支持克隆taskschains,尽管增加对groups的支持将是一个简单的扩展

def clone_signature(sig, args=(), kwargs=(), **opts):
    if sig.subtask_type and sig.subtask_type != "chain":
        raise NotImplementedError(
            "Cloning only supported for Tasks and chains, not %s" % sig.subtask_type
        )
    clone = sig.clone()
    if hasattr(clone, "tasks"):
        t = clone.tasks[0]
    else:
        t = clone
    args, kwargs, opts = t._merge(args=args, kwargs=kwargs, options=opts)
    t.update(args=args, kwargs=kwargs, options=deepcopy(opts))
    return clone