AsyncIO中异步任务内的第二个await何时执行?
问题解答
你的理解存在误区:asyncio.as_completed并不是只处理每个协程的第一个await,它等待的是整个任务的完成——也就是每个httpx_get协程从开始到执行完所有代码的全过程。下面详细拆解第二个await的执行逻辑:
核心执行流程
任务初始化与第一轮暂停
所有asyncio.create_task创建的任务会被事件循环调度执行,每个任务先运行到第一个await client.get(url):此时该任务会暂停,让出CPU给事件循环,事件循环会切换到其他还未暂停的任务继续执行,直到所有任务都停在第一个HTTP请求的等待阶段。第一个请求完成后的执行
当某个任务的第一个HTTP请求响应返回后,事件循环会重新调度该任务,从暂停处继续执行:- 先完成
... other computation ...的代码逻辑 - 然后执行到第二个
await client.get(url),此时任务再次暂停,等待第二个HTTP请求的响应,同时事件循环再次切换到其他就绪的任务(比如其他完成了第一个请求、正在执行中间计算,或者还在等待第一个请求的任务)。
- 先完成
任务的最终完成
只有当某个任务完成了第二个HTTP请求的等待,且执行完httpx_get中所有后续代码(如果有的话),这个任务才会被标记为完成,此时asyncio.as_completed的迭代器才会返回这个任务的协程对象,await coro会获取到该任务的最终返回值(你的代码中httpx_get没有return,所以返回None)。
关于第二个请求的并发逻辑
第二个请求并不是“所有同时执行并等待”,而是:
- 每个任务的第二个请求必须在自身第一个请求完成、中间计算执行完之后才会发起
- 多个任务的第二个请求会和其他任务的执行步骤(比如其他任务的中间计算、第一个请求等待)交替进行,实现并发处理
- 事件循环会根据I/O完成的时机,动态调度各个任务的执行,确保CPU不会闲置
简化执行顺序示例
假设三个任务对应Google、Yahoo、Youtube:
- 事件循环依次启动三个任务,都停在第一个HTTP请求等待
- Google的第一个请求先完成 → 任务继续执行中间计算 → 发起第二个请求并暂停
- 此时Yahoo的第一个请求完成 → 任务继续执行中间计算 → 发起第二个请求并暂停
- Google的第二个请求完成 → 任务执行完剩余代码 → 任务完成,被
as_completed返回 - Youtube的第一个请求完成 → 任务继续执行中间计算 → 发起第二个请求并暂停
- Yahoo的第二个请求完成 → 任务完成,被
as_completed返回 - Youtube的第二个请求完成 → 任务完成,被
as_completed返回
内容的提问来源于stack exchange,提问作者rooter
相关产品推荐
相关产品推荐

