从同步函数调用asyncio时打印输出顺序不符合预期问题求解
问题原因
你遇到的输出顺序不符合预期的核心原因是对await的执行逻辑理解有误:
- 在异步协程中,
await 协程对象的作用是挂起当前协程,等待被调用的协程完全执行完毕后,才会继续执行当前协程的后续代码,并非将协程提交到事件循环后就立即执行后续逻辑。
你的main_async是顺序调用await foo()、await bar(),执行流程完全是串行的:
- 先执行
foo协程,打印before the sleep,遇到await asyncio.sleep(2)后挂起2秒 - 2秒后
foo唤醒,打印world,foo协程执行完毕,返回main_async - 才开始执行
bar协程,打印hello
因此最终输出顺序是before the sleep → world → hello,和你实际运行的结果一致。
预期效果实现方案
如果要让foo和bar并发执行,得到你想要的输出顺序,需要先将两个协程封装为异步任务提交到事件循环,再统一等待执行完成,示例代码如下:
import asyncio def main(): asyncio.run(main_async()) async def main_async(): # 先创建异步任务,提交到事件循环后立即返回,不会等待任务执行完成 task_foo = asyncio.create_task(foo()) task_bar = asyncio.create_task(bar()) # 等待所有任务执行完成 await task_foo await task_bar # 也可以用asyncio.gather简化写法:await asyncio.gather(foo(), bar()) async def foo(): print('before the sleep') await asyncio.sleep(2) print('world') async def bar(): print('hello') await asyncio.sleep(0) if __name__=='__main__': main()
上述代码的执行流程:
main_async运行后先创建foo任务,foo立即执行打印before the sleep,遇到sleep(2)后挂起,控制权交回main_asyncmain_async继续创建bar任务,bar立即执行打印hello,遇到sleep(0)后挂起,控制权交回main_async- 等待2秒后
foo唤醒,打印world,所有任务执行完成
最终输出完全符合你的预期:
before the sleep
hello
world
内容的提问来源于stack exchange,提问作者darren
相关产品推荐
相关产品推荐

