芹菜:如何忽略和弦或链中的任务结果?

时间:2012-11-29 15:51:06

标签: python asynchronous task celery

我正在使用芹菜,我有几个需要按顺序执行的任务。

例如我有这个任务:

@celery.task
def tprint(word):
    print word

我想做这样的事情:

>>> chain(tprint.s('a') | tprint.s('b'))()

然后我得到TypeError: tprint() takes exactly 1 argument (2 given)

与和弦相同,在这种情况下我需要在一组任务后执行任务:

>>> chord([tprint.s('a'), tprint.s('b')])(tprint.s('c'))

那么如何处理这种情况呢?我不关心每项任务的结果,但需要按顺序执行。


添加第二个参数将无效:

@celery.task
def tprint(word, ignore=None):
    print word

>>> chain(tprint.s('a', 0) | tprint.s('b'))()

这将打印出'a'和'None'。

4 个答案:

答案 0 :(得分:56)

有一个内置功能可以忽略链接中的结果和其他 - 不可变的子任务。您可以使用.si()快捷方式而不是.s()或.subtask(immutable = True)

此处有更多详情:http://docs.celeryproject.org/en/master/userguide/canvas.html#immutability

答案 1 :(得分:3)

已经发布了一个可能的解决方案,但我想补充进一步的澄清和替代解决方案(在某些情况下是一个更好的解决方案)。

您看到的错误,表明您的任务的签名需要考虑第二个参数,这是因为当在chain中调用任务时,Celery会自动推送每个任务{{1作为以下任务的第一个参数。

来自docs:

  

任务可以链接在一起,这实际上意味着添加回调任务:

result
  

链接任务将应用其父任务的结果作为第一个参数

因此,在您的情况下,您可以像这样重写您的任务:

>>> res = add.apply_async((2, 2), link=mul.s(16))
>>> res.get()
4

如果你不打算对结果做任何事情,你可以忽略它,changing the decorator thus

@celery.task
def tprint(result, word):
    print word

然后您不必更改任务签名。

对不起,最后一点需要进一步研究。

答案 2 :(得分:-1)

您可以尝试做这样的事情。 您可以使用2个参数

,而不是为函数tprint提供单个参数
def tprint(word, x=None):
    print word

然后

chain(tprint.s('a', 0) | tprint.s('b'))()

答案 3 :(得分:-2)

最后找到一个解决方法,链式装饰器将完成这项工作。

我不知道芹菜究竟是怎么做到的,但芹菜似乎强迫将前一任务的结果绑定到下一个任务的第一个参数。

所以这是一个例子:

def chain_deco(func):

    @functools.wraps(func)
    def wrapper(chain=None, *args, **kwargs):
        if chain is False:
            return False

        func(*args, **kwargs)
        return True

    return wrapper


@celery.task
@chain_deco
def hello(word):
    print "hello %s" % word

现在这将给出正确的输出。

>>> (hello.s(word='a') | hello.s(word='b'))()

OR

>>> (hello.s('a') | hello.s('b'))(True)

装饰器还提供了在中间停止链的能力(使后来的级联失败。)

同样的机制也适用于chord