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

对Python异步生成器(asyncio)执行行为的困惑求助

异步生成器执行逻辑误区解析

先看这段模拟远程数据库取值的代码:

import asyncio

async def async_gen():
    for i in range(5):
        print(f"entering iteration {i}")
        await asyncio.sleep(3)
        print(f"ending iteration {i}")
        yield i

async def main():
    async for value in async_gen():
        print(value)

asyncio.run(main())

预期vs实际差异

  • 预期:所有entering iteration i瞬间打印,3秒后所有ending iteration i和数值依次输出,总耗时3秒。
  • 实际:每次迭代的entering和ending间隔3秒,5次迭代总耗时15秒,输出是逐次完成的。

核心误区:异步生成器不是并发执行

异步生成器的async for是顺序迭代的:

  1. 第一次async for触发async_gen()执行,走到yield i时暂停,返回值0;
  2. 打印0后,第二次async for才会让async_gen()从暂停处继续执行下一轮循环;
  3. 每一轮循环里的await asyncio.sleep(3)会阻塞当前迭代的执行,直到休眠完成,才会进入下一次迭代。

简单说:异步生成器的迭代是串行的,前一次迭代没走完,下一次不会开始,自然没法实现你想要的并发效果。

实现预期效果的正确方式

如果要让多个取值任务并发执行,应该用asyncio.gather来批量调度异步任务,代码如下:

import asyncio

async def fetch_data(i):
    print(f"entering iteration {i}")
    await asyncio.sleep(3)
    print(f"ending iteration {i}")
    return i

async def main():
    # 创建所有异步任务
    tasks = [fetch_data(i) for i in range(5)]
    # 并发执行所有任务,等待全部完成后获取结果
    results = await asyncio.gather(*tasks)
    for result in results:
        print(result)

asyncio.run(main())

这段代码的执行逻辑:

  • 所有fetch_data任务会被同时提交给事件循环,瞬间打印所有entering iteration i;
  • 3秒后所有休眠同时结束,依次打印ending iteration i和对应的结果,总耗时仅3秒,完全符合预期。

内容的提问来源于stack exchange,提问作者Youcef Kacer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:56:07