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

如何在Python中让异步协程尽早启动实现eager执行?

解决方案

Python异步协程默认是懒执行的:直接调用异步函数返回的协程对象只有被await时才会执行;用asyncio.create_task提交到事件循环后,也需要当前运行的协程主动让出CPU,任务才会被调度执行。你之前用await asyncio.sleep(0)的逻辑是对的,属于事件循环标准的主动让出操作,只是写法冗余,可以通过封装工具函数优化。

最简实现方案

封装通用的提前启动工具函数,一次调用即可让嵌套的所有协程都执行到第一个IO挂起点:

import asyncio
from typing import Coroutine, Task

async def early_start(coro: Coroutine) -> Task:
    # 先把协程包装成任务加入事件循环就绪队列
    task = asyncio.create_task(coro)
    # 主动让出CPU,让事件循环调度所有就绪任务到首次IO阻塞
    await asyncio.sleep(0)
    return task

改造后的业务代码:

async def subsubfunc():
    print("    subsubfunc")
    # [some async I/O code here] 此处IO操作触发挂起,自动让出CPU

async def subfunc():
    print("  subfunc A")
    subsub_task = await early_start(subsubfunc())
    print("  subfunc B")
    await subsub_task
    print("  subfunc C")

async def func():
    print("func A")
    sub_task = await early_start(subfunc())
    print("func B")
    await sub_task
    print("func C")

asyncio.run(func())

运行上述代码输出完全匹配你的期望,且不需要多次重复写await asyncio.sleep(0),嵌套层级再多也只需要每个子任务调用一次early_start即可。

适用场景说明

这个方案完美匹配你提到的「先发请求再做其他操作」的需求:

  • 调用early_start后,所有子协程会执行到IO请求发送完成、等待响应的挂起点,自动把CPU交还给调用方
  • 调用方此时可以执行其他不需要等待响应的业务逻辑,最后再await任务拿到返回结果即可

如果不想封装工具函数,也可以直接用asyncio.wait实现等价逻辑,语义上更偏向任务调度:

task = asyncio.create_task(subfunc())
# 等待0秒,仅让就绪的任务执行到挂起点就返回
await asyncio.wait([task], timeout=0)

内容的提问来源于stack exchange,提问作者Al Gebra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:09:02