为何Python中创建任务即运行协程?asyncio代码疑问解析
Python Asyncio 常见疑问解答
疑问1:create_task后协程为何立即执行,输出顺序不符合预期?
代码示例
import asyncio async def fetch_data(param): print(f"Do something with {param}...") await asyncio.sleep(param) print(f"Done with {param}") return f"Result of {param}" async def main(): task1 = asyncio.create_task(fetch_data(1)) task2 = asyncio.create_task(fetch_data(2)) result2 = await task2 print("Task 2 fully completed") result1 = await task1 print("Task 1 fully completed") return [result1, result2] results = asyncio.run(main()) print(results)
实际与预期差异
预期首行输出Do something with 2...,实际首行是Do something with 1...,且创建任务后协程就开始执行,而非等待await才启动。
核心原因
asyncio.create_task的行为并非仅“注册协程到事件循环”,而是创建任务后,事件循环会尽快调度该协程执行,直到遇到第一个await挂起点。具体执行流程:
asyncio.run(main())启动事件循环,运行main协程。- 创建
task1时,fetch_data(1)立即执行,直到遇到await asyncio.sleep(1),协程挂起,控制权返回给main。 - 创建
task2时,fetch_data(2)同理执行到await asyncio.sleep(2),挂起后返回控制权给main。 main执行await task2时挂起,事件循环等待任务完成:先等到task1的sleep(1)结束,执行Done with 1;再等到task2的sleep(2)结束,执行Done with 2,随后唤醒main继续执行后续代码。
你的理解误区在于认为await才会触发协程启动,实际上create_task就会触发协程执行到第一个挂起点。
疑问2:未await任务,协程为何运行了一部分,后续代码未执行?
代码示例
import asyncio async def fetch_data(param): print(f"Do something with {param}...") await asyncio.sleep(param) print(f"Done with {param}") return f"Result of {param}" async def main(): task1 = asyncio.create_task(fetch_data(1)) task2 = asyncio.create_task(fetch_data(2)) results = asyncio.run(main()) print(results)
实际输出分析
Do something with 1...和Do something with 2...被执行:因为创建任务时,协程会立即执行到第一个await asyncio.sleep(param)挂起点,这部分同步代码会直接运行。print(f"Done with {param}")未执行:当main协程创建完任务后就执行完毕,asyncio.run()会立即关闭事件循环,所有未完成的任务(处于sleep挂起状态的fetch_data)会被强制取消,无法从sleep中唤醒,因此后续代码不会执行。- 输出
None:因为main协程没有显式return值,默认返回None。
内容的提问来源于stack exchange,提问作者M a m a D
相关产品推荐
相关产品推荐

