为何未使用await时asyncio.create_task创建的任务仍会执行?
关于asyncio.create_task()执行时机的疑问解答
通常资料提到asyncio.create_task(c)会“立即”运行协程c,区别于直接调用协程必须await才执行。但实际任务要执行到第一个await才会被调度启动,不过测试发现完全不使用await时,程序结束前创建的任务仍会执行第一步,以下是示例代码及输出:
示例代码
import asyncio async def counter_loop(x, n): for i in range(1, n + 1): print(f"Counter {x}: {i}") await asyncio.sleep(0.5) return f"Finished {x} in {n}" async def main(): slow_task = asyncio.create_task(counter_loop("Slow", 4)) fast_coro = asyncio.create_task(counter_loop("Fast", 2)) print("Created tasks") for _ in range(1000): pass print("main ended") asyncio.run(main()) print("program ended")
输出结果
Created tasks main ended Counter Slow: 1 Counter Fast: 1 program ended
原因解释
这个现象和asyncio事件循环的shutdown阶段行为直接相关:
- 调用
asyncio.create_task时,协程会被包装成任务加入事件循环的任务队列,但不会立刻打断当前运行的main协程——main会继续执行直到自身结束。 - 当
main协程执行完毕,asyncio.run()会触发事件循环进入shutdown流程。此时事件循环会调度所有已提交但未完成的任务,让它们运行到第一个await暂停点,或者任务完成。 - 你的
counter_loop协程中,第一个print语句在await asyncio.sleep(0.5)之前,所以任务会先执行这个print,随后遇到await暂停。但事件循环处于shutdown阶段,不会等待任务恢复执行,直接终止循环。 - 最后事件循环退出,程序执行
print("program ended")。
如果希望任务完全执行完毕,需要在main中显式await创建的任务,比如在print("main ended")前添加await slow_task和await fast_coro,这样事件循环会等待任务完成后再进入shutdown。
内容的提问来源于stack exchange,提问作者user118967
相关产品推荐
相关产品推荐

