是否保证作为asyncio.gather
参数的协程将
预定并保留订单?考虑以下示例:
import asyncio
async def coro(i):
print('{i} finished'.format(i=i))
async def main():
await asyncio.gather(
coro(0),
coro(1),
coro(2),
coro(3),
coro(4),
)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
和结果:
0 finished
1 finished
2 finished
3 finished
4 finished
答案 0 :(得分:6)
可等待的asyncio.gather(* aws,loop = None,return_exceptions = False)
在aws序列中同时运行等待的对象。
如果aws中有待等待的协程,则会自动安排 作为任务。
如果所有等待项均成功完成,则结果为 返回值的汇总列表。 结果值的顺序 对应于aws中等待的顺序。
因此保留了结果值的顺序,但没有保留执行顺序。
答案 1 :(得分:1)
是的,至少从cpython实现的源代码中,将按顺序安排它们。迭代协程序列表,并将任务逐一添加到循环中。尽管我看不到在哪种情况下,计划保证变得很重要。不能保证循环将按顺序执行它们,也不能保证它们将按该顺序完成。我认为这将取决于特定循环的实现细节和代码的性质。例如,尝试在打印之前将asyncio.sleep(1)添加到协同例程中。
答案 2 :(得分:0)
在一个有趣的极端情况下,至少在Python 3.6中,顺序中断了。
让我们举一个这样的例子:
WAR
Py36的近似结果:
import asyncio
async def main():
data = [1, 2, 3, 4, 5, 6, 7, 8]
async def aiter(iterable):
for v in iterable:
yield v
aiterable = aiter(data)
aiterables = [aiterable] * 8
values = await asyncio.gather(
*[it.__anext__() for it in aiterables])
assert values == data, f'{values} != {data}'
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
此行为看起来合乎逻辑,因为AssertionError: [7, 6, 3, 4, 5, 2, 8, 1] != [1, 2, 3, 4, 5, 6, 7, 8]
协程以任意顺序执行。但是,在Py37 +中,代码可以正常工作,并且保留输出列表顺序。我在文档中没有找到任何提及。