关于Python异步代码输出内容及顺序的疑问
嗨,我来帮你把这段异步代码的输出逻辑掰扯清楚~
先回顾下你的代码和实际输出:
你写的代码:
import asyncio async def my_coroutine(): print("Coroutine started") await asyncio.sleep(5) print("Coroutine finished") async def main(): print('a') asyncio.create_task(my_coroutine()) print('b') asyncio.run(main())
实际输出:
a b Coroutine started
你原本以为只会输出a和b,现在困惑为什么多了Coroutine started,以及它的打印顺序,我来给你拆解:
首先得搞懂asyncio.create_task()的作用——它就像你给Python的异步事件循环递了个待办条:“等你手头的事忙完,帮我跑一下这个协程哈”。它不会立刻暂停当前代码去执行新任务,而是让当前的main协程先把手上的事做完。
那为什么Coroutine started会打印出来?因为当main执行完print('b')后就彻底结束了,这时候事件循环终于有空了,翻到待办条里的my_coroutine,就开始执行它。
my_coroutine一启动就先打印了Coroutine started,紧接着遇到await asyncio.sleep(5)——这步是告诉事件循环:“我要歇5秒,这段时间你可以去忙别的”。但此时事件循环回头一看,主协程main已经跑完了,也没有其他待办任务,按照asyncio.run()的规则,它会直接关闭事件循环,把还在“睡觉”的my_coroutine打断,所以Coroutine finished根本没机会打印。
你之前的预期偏差,可能是误以为只要不await任务,它就永远不会被执行。但实际上,asyncio.run()在主协程结束后,会先检查已提交的后台任务,只要任务还没遇到需要等待的await,它会先把能跑的代码执行完,直到遇到挂起操作才会终止循环。
如果想让my_coroutine完全不执行,那就别用create_task提交它;如果提交了但不想运行,可以在main结束前手动取消任务。反过来,要是想让它完整执行完,你需要在main里await这个任务,比如改成这样:
async def main(): print('a') task = asyncio.create_task(my_coroutine()) print('b') await task
这样main在打印b后会等待my_coroutine执行完毕,5秒后就能看到Coroutine finished了。
备注:内容来源于stack exchange,提问作者ankit

