我有一个有趣的问题,试图克隆一个芹菜链供小组使用,我的预期用例类似于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
此功能是否因某种原因而被破坏,不受支持,或者我是难以置信的钝器并且做错了什么事?
答案 0 :(得分:0)
因此,事实证明,核心问题是通过回旋过程,clone调用构造函数进行链式创建新实例。此构造函数不接受任何应用于该链的args或kwargs,而是将它们默认为空值,从而导致它们丢失。
目前,我的解决方案是通过创建自己的克隆方法(该方法修改链中第一个任务的参数)来解决此问题。设置args属性时似乎也可以使用,如果再次在芹菜中克隆该链时,存储在其中的值将丢失。
我的克隆方法目前支持克隆tasks
和chains
,尽管增加对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