You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么await第二个asyncio任务时,未被await的第一个任务仍会运行

问题

以下是基于Python 3.10编写的异步代码:

import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    t1 = asyncio.create_task(say_after(1, 'task 1'))
    t2 = asyncio.create_task(say_after(2, 'task 2'))

    print(f'Start at {time.strftime("%X")}')

    await t2

    print(f'End at {time.strftime("%X")}')

asyncio.run(main(), debug=True)

代码运行后输出如下:

Start at 03:32:50
task 1
task 2
End at 03:32:52

代码中仅对t2执行了await操作,并未显式await t1,但t1仍然正常运行完成,该代码修改自Python官方文档asyncio-task章节的示例,该现象出现的原因是什么?

原因说明
  • 先搞懂asyncio.create_task()的基本逻辑:只要你调用了这个方法,传入的协程会立刻被包装成Task,丢到当前运行的事件循环的待调度队列里。事件循环处于运行状态时,队列里所有Task都会按调度规则自动执行,根本不需要你挨个await才会启动。await某个Task的作用只是把当前协程挂起,等这个Task跑完再往下走,它从来不是启动Task的开关。
  • 这段代码里执行await t2时,main协程会挂起整整2秒等待t2结束。这2秒的挂起窗口内事件循环始终在正常运行,会轮询处理所有已注册、到达执行时机的Task:t1只需要等待1秒就能执行,自然会在这个窗口内被调度运行,打印出task 1,完全不需要单独对它执行await。
  • 这个运行结果存在巧合性:如果把t2的等待时间改成小于1秒(比如0.5秒),那await t2只会让main协程挂起0.5秒就恢复执行,等main协程运行到结束时,asyncio.run()会直接取消所有还没执行完成的后台Task,这时候t1还没等够1秒就会被强制终止,无法完整执行。当前示例里await t2等待的2秒刚好长于t1需要的1秒执行时间,给够了t1运行窗口,才会出现没显式await也正常跑完的效果。

内容的提问来源于stack exchange,提问作者De Scar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:33:19