async def 函数中不能用 yield from 委托异步生成器,会报 SyntaxError;正确方式是 async for 遍历再 yield,以兼容 aiter__/__anext 协议并支持取消。
async def 定义的是协程函数或异步生成器,但 yield from 本身不支持 await 行为,所以不能直接在 async def 函数中使用 yield from 委托另一个异步生成器。Python 会抛出 SyntaxError: 'yield from' inside async function。
这是因为 yield from 是同步委托协议(基于 __iter__ 和 send()),而异步生成器走的是 __aiter__ / __anext__ 协议,二者不兼容。
async for + yield
yield from 可以用,但整个函数不能是 async def(否则类型混用会出逻辑问题)async def 中 yield from 同步生成器,虽然语法允许,但会阻塞事件循环必须显式迭代并逐个 yield,即用 async for 遍历目标异步生成器,再用 yield 转发值。这是唯一符合语义且不破坏异步流的方式。
async def inner():
yield 1
yield 2
async def outer():
async for x in inner(): # ✅ 正确:用 async for 拉取
yield x # ✅ 再 yield 出去
yield from inner() —— 语法错误yield await inner() —— inner() 返回的是异步生成器对象,不是可 await 的协程async for 会自动调用 aclose(),这点比手动管理更安全在 def 定义的同步生成器里,yield from 是语法糖,等价于手动 for + yield,并自动处理 StopIteration、throw()、close() 等委托逻辑。
def sync_inner():
yield 'a'
yield 'b'
def sync_outer():
yield from sync_inner() # ✅ 合法,且会透传 close()/throw()
__iter__ 和 send(),全程同步阻塞
yield from(如 yield from async_gen()),运行时会报 TypeError: 'async_generator' object is not iterable
awaitable,也无法绕过协议不匹配的根本限制异步生成器的每次 yield 都对应一次 await __anext__() 调用,涉及事件循环调度;而 yield from 的委托是纯用户态栈操作,无调度开销。两者调度粒度和错误传播路径完全不同。
async for + yield 多一层协程帧,但保证了 await 点清晰、取消信号可捕获loop.run_in_executor 包装同步 yield from 来“桥接”,会导致事件循环被阻塞,完全违背异步初衷yield from awaitable 的语法糖,也不太可能加——协议层级差异太大真正容易被忽略的是异常传播:在 async for 块中,GeneratorExit 会变成 AsyncGeneratorExit,且 throw() 不再可用,只能靠 aclose() 或取消任务来中断。