import time
import random
import asyncio
async def waiter(name):
for _ in range(6):
time_to_sleep = random.randint(1, 3) / 4
time.sleep(time_to_sleep)
#await asyncio.sleep(time_to_sleep)
print(
"{} waited {} seconds"
"".format(name, time_to_sleep)
)
async def main():
await asyncio.wait([waiter("foo"), waiter("bar")])
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
两个协程中的代码都得到全部执行,执行的先后顺序不定,可能先执行foo,也可能先执行bar.(实验时,貌似是固定的顺序,可以改下循环里的次数)
4次时:
D:\Anaconda\python.exe D:/pythonTest/hello/testcoroutine.py
foo waited 0.5 seconds
foo waited 0.25 seconds
foo waited 0.25 seconds
foo waited 0.5 seconds
bar waited 0.75 seconds
bar waited 0.25 seconds
bar waited 0.5 seconds
bar waited 0.75 seconds
Process finished with exit code 0
6次时:
D:\Anaconda\python.exe D:/pythonTest/hello/testcoroutine.py
bar waited 0.5 seconds
bar waited 0.5 seconds
bar waited 0.5 seconds
bar waited 0.5 seconds
bar waited 0.5 seconds
bar waited 0.75 seconds
foo waited 0.25 seconds
foo waited 0.5 seconds
foo waited 0.25 seconds
foo waited 0.5 seconds
foo waited 0.5 seconds
foo waited 0.75 seconds
Process finished with exit code 0
这里因为time.sleep 是阻塞的,所以要么是foo 全部打印完,要么是bar 全部打印完。
如果将 time.sleep注释掉,采用下边被注释掉的await asycio.sleep,打印结果可能如下:
D:\Anaconda\python.exe D:/pythonTest/hello/testcoroutine.py
foo waited 0.25 seconds
bar waited 0.5 seconds
bar waited 0.25 seconds
foo waited 0.5 seconds
foo waited 0.5 seconds
bar waited 0.75 seconds
foo waited 0.25 seconds
foo waited 0.25 seconds
bar waited 0.75 seconds
foo waited 0.5 seconds
bar waited 0.75 seconds
bar waited 0.5 seconds
Process finished with exit code 0
asycio.sleep 也被加入到事件循环中被调度,所以出现 foo 和 bar 的交叉打印。每次运行到 await 处,此协程将await后的对象传递给事件循环,等待结果的返回。然后控制流进入事件循环处理事件。处理完事件,将结果返回给等待该结果的协程,接着执行获取该结果的协程。
foo 和 bar交替执行,主动让出控制流。这与普通的函数调用中的调用者与被调用者的关系是完全不同的:被调用者的状态在控制流回到调用者之后完全丢弃,谈不上再恢复。