【发布时间】:2020-12-04 01:00:29
【问题描述】:
在以下代码中,创建了一个任务 A,并将其添加到一组任务 tasks。
然后我使用await asyncio.wait(tasks) 等待任务完成。
但这没有考虑任务B1,它是在内部任务A(递归函数调用)创建的。
那么下面的代码不会等待B1 完成:看下面的结果,任务B1 永远不会完成。
我认为原因是当tasks 在第(**) 行求值时,它仍然有一个单一元素。
问题:如何让await asyncio.wait(tasks) 处理不断发展/不断增长的任务集?
import asyncio
tasks = set()
i = 0
async def mytask(s):
global i
print('mytask %s starting' % s)
await asyncio.sleep(1)
if i < 4: # limit number of tasks
print('mytask %s creating new task' % s)
i += 1
tasks.add(asyncio.create_task(mytask('B%i' % i)))
print('mytask %s len tasks:' % s, len(tasks))
await asyncio.sleep(0.5)
print('mystak %s finished' % s)
async def main():
print('main starting')
tasks.add(asyncio.create_task(mytask('A')))
print('len tasks:', len(tasks))
await asyncio.wait(tasks) # (**)
# await asyncio.sleep(10)
print('main finished')
asyncio.run(main())
结果:
main starting
len tasks: 1
mytask A starting
mytask A creating new task
mytask A len tasks: 2
mytask B1 starting # <--- mytask B1 will never complete!
mystak A finished
main finished
如果我们将 (**) 行替换为await asyncio.sleep(10),当然所有任务都会完成:
main starting
len tasks: 1
mytask A starting
mytask A creating new task
mytask A len tasks: 2
mytask B1 starting
mystak A finished
mytask B1 creating new task
mytask B1 len tasks: 3
mytask B2 starting
mystak B1 finished
mytask B2 creating new task
mytask B2 len tasks: 4
mytask B3 starting
mystak B2 finished
mytask B3 creating new task
mytask B3 len tasks: 5
mytask B4 starting
mystak B3 finished
mytask B4 len tasks: 5
mystak B4 finished
main finished
【问题讨论】:
-
任务 A 不能简单地等待函数 B 吗?这样你就可以只等待顶级任务而不是整个树。
-
任务递归创建新任务,我编辑了一个更好的例子,@user4815162342。
-
当然,但是每个任务都可以等待它直接创建的任务(连同它自己的工作)。这样,每个任务都对其直接产生的东西“负责”,并且您不需要维护全局集。例如,请参阅我的答案。
标签: python asynchronous async-await python-asyncio