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

Python异步协程与生成器:能否用两个协程分别迭代异步生成器并等待其终止?

问题解答

你不能按照示例中的方式实现需求,核心有两个问题:

1. 异步生成器不是可等待对象,直接await gen会报错

异步生成器实现的是__aiter__和__anext__接口,用于支持async for迭代;而await要求对象必须是可等待对象(实现__await__方法,或是协程、任务、Future实例)。直接await异步生成器实例会触发TypeError: cannot await an async generator。

你的示例代码首先要修正协程定义的语法(添加async def),但即使修正后,coro2里的await gen依然会报错。

2. 同一个异步生成器不能被多个协程同时操作

异步生成器的内部状态是单线程维护的,每次async for迭代都会调用__anext__推进状态。如果两个协程同时操作同一个生成器实例,会导致状态错乱,迭代逻辑完全失控——比如一个协程刚推进到某一步,另一个协程又调用__anext__,破坏生成器的执行流程。

正确实现方式

如果想让一个协程等待异步生成器的迭代终止,应该等待负责迭代的协程任务完成,或者用同步原语(如asyncio.Event)来传递迭代完成的信号。

方式一:等待迭代协程任务

import asyncio

async def async_gen():
    # 示例异步生成器
    for i in range(3):
        yield i
        await asyncio.sleep(0.5)

async def coro1(gen):
    async for _ in gen:
        await asyncio.sleep(1)
        print("coro1 处理了一个元素")

async def coro2(iter_task):
    await iter_task  # 等待迭代协程完成
    print('生成器迭代完成')

async def main():
    gen = async_gen()
    # 创建迭代协程的任务
    iter_task = asyncio.create_task(coro1(gen))
    # 让coro2等待这个任务结束
    await coro2(iter_task)

asyncio.run(main())

方式二:用asyncio.Event通知完成

import asyncio

async def async_gen():
    for i in range(3):
        yield i
        await asyncio.sleep(0.5)

async def coro1(gen, done_event):
    async for _ in gen:
        await asyncio.sleep(1)
        print("coro1 处理了一个元素")
    done_event.set()  # 迭代完成后触发事件

async def coro2(done_event):
    await done_event.wait()  # 等待迭代完成的信号
    print('生成器迭代完成')

async def main():
    gen = async_gen()
    done_event = asyncio.Event()
    # 同时运行两个协程
    await asyncio.gather(
        coro1(gen, done_event),
        coro2(done_event)
    )

asyncio.run(main())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 03:34:54