为什么在Celery中构建一组链条导致异常?

时间:2016-12-29 01:14:27

标签: python python-3.x asynchronous celery celery-task

我提前为没有提供MVCE而道歉 - 不幸的是由于这个问题的性质,它不适合最少的例子。我认为,如果没有MVCE,它仍然会很有责任。

我有一个任务列表,客户端可以从中选择要在Flask中创建的任务子集。我创建了这样的任务:

current_app.logger.info("Creating list of chained tasks..")
chains = [functools.reduce(
    lambda x, y: x | y.s(foo, bar), remaining_tasks, first_task.s(foo, bar)
) for foo in foos]

所有任务都有类似的功能签名,类似于

@celery.task
def my_task(baz, foo, bar):
    # ...
    return baz

我尝试按以下方式执行该组:

current_app.logger.info("Created a group of chained tasks..")
g = group(*chains)
res = g.apply_async(args=(baz,), queue="default")

我发现在调用apply_async时会引发两个异常:

Traceback (most recent call last):
  File "/Users/erip/.virtualenvs/foo/lib/python3.5/site-packages/celery/utils/functional.py", line 209, in __getitem__
    return self.__consumed[index]
IndexError: list index out of range

File "/Users/erip/Code/whatever.py", line 101, in blahblah
    res = g.apply_async(args=(baz,), queue="default")
  File "/Users/erip/.virtualenvs/foo/lib/python3.5/site-packages/celery/canvas.py", line 977, in apply_async
    app = self.app
  File "/Users/erip/.virtualenvs/foo/lib/python3.5/site-packages/celery/canvas.py", line 1144, in app
    app = self.tasks[0].app
  File "/Users/erip/.virtualenvs/foo/lib/python3.5/site-packages/celery/utils/functional.py", line 213, in __getitem__
    self.__consumed.append(next(self.__it))
TypeError: 'Signature' object is not an iterator

docs表明我的链构造是有效的,所以我不明白为什么异步应用程序会导致问题。

我的目标是创建一组len(foos)个链,这些链是异步应用的。我发现这种行为只发生在len(foos) == 1

之前有没有人遇到过这个问题?

1 个答案:

答案 0 :(得分:2)

我遇到过类似的问题,芹菜文档有以下注意事项:

  

如果只传递一个参数,并且该参数是可迭代的      然后,这将被用作任务列表:这个      允许我们将group与生成器表达式一起使用。

看一下Group类的构造函数。如果我们只传递一个签名来初始化对象,则此签名将被视为生成器。

def __init__(self, *tasks, **options):                                       
    if len(tasks) == 1:                                                      
        tasks = tasks[0]                                                     
        if isinstance(tasks, group):                                         
            tasks = tasks.tasks                                              
        if not isinstance(tasks, _regen):                                    
            tasks = regen(tasks)                                             
    Signature.__init__(                                                      
        self, 'celery.group', (), {'tasks': tasks}, **options                
    )                                                                        
    self.subtask_type = 'group'  

在您的情况下,您可以通过以下方式执行一组任务:

current_app.logger.info("Created a group of chained tasks..")
if len(chains) == 1:
    g = group(chains)
else:
    g = group(*chains)
res = g.apply_async(args=(baz,), queue="default")