【发布时间】:2019-04-11 09:33:07
【问题描述】:
需要:Python 3.7 或更高版本。
下面定义了两个函数main1 和main2。一个创建任务,然后在最后等待所有任务;另一个创建并一次等待。
main1 需要 2 秒,main2 需要 30 秒。为什么?
import asyncio
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main1():
tasks = []
for _ in range(10):
task1 = asyncio.create_task(say_after(1, 'hello'))
task2 = asyncio.create_task(say_after(2, 'world'))
tasks.append(task1)
tasks.append(task2)
for x in tasks:
await x
async def main2():
for _ in range(10):
await asyncio.create_task(say_after(1, 'hello'))
await asyncio.create_task(say_after(2, 'world'))
asyncio.run(main2())
编辑 1:
这是一个main3 版本,需要 20 秒。我想说整个事情只是出于直觉:(
async def main3():
for _ in range(10):
task1 = asyncio.create_task(say_after(1, 'hello'))
task2 = asyncio.create_task(say_after(2, 'world'))
await task1
await task2
编辑 2:
(下面添加了更多示例代码)我已经阅读了@freakish 的详细答案,但我仍然停留在一点:所以只有连续的await 才能整体并行工作(main4) ?
既然create_task() 不需要时间(对吗?),为什么不在main5 中的两个await 都在后台运行,这样main5 将花费(task1,task2)的最大时间?
这是 await 机制的设计,还是只是 asyncio 的限制(在设计或实现中)?
以及在官方 Python 文档中定义的任何 await 详细行为?
# took 2 seconds
async def main4():
task1 = asyncio.create_task(say_after(1, 'hello'))
task2 = asyncio.create_task(say_after(2, 'world'))
await task1
await task2
# took 3 seconds
async def main5():
task1 = asyncio.create_task(say_after(1, 'hello'))
await task1
task2 = asyncio.create_task(say_after(2, 'world'))
await task2
【问题讨论】:
-
why not both two await in main5 run in background他们有。在 task1 完成之前,它只是task2不存在。因为task2 = create_task(...)之前有await task1。await指令(与 create_task 不同)阻止代码前进,直到任务完成。 -
@freakish 所以在 asyncio 中没有什么神器可以“预见”协程中的所有任务并使它们协同工作?我能说 asyncio 不够聪明吗(即为什么要创建的 task2(在 main5 中)必须等待第一个
await完成,无论如何都要等待) -
Asyncio 不是预言机,你是对的。但不够聪明?锤子不聪明吗?它是一个工具,这取决于你如何使用它。正如您在我的回答中看到的,您可以创建许多 非等效 流。没有更好/更差的流程。它们中的每一个都有优点和缺点,可能有用,这取决于您要实现的目标。归根结底,只有程序员知道他想在哪里等待。没有编译器/解释器可以为您做出决定。
标签: python python-3.x python-asyncio