我提前为没有提供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
。
之前有没有人遇到过这个问题?
答案 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")