yield from 在 python 3.5+ 异步编程中已被禁用,仅适用于同步生成器委托;async def 中使用会报 syntaxerror,旧式 @asyncio.coroutine 协程已弃用并移除,await 才是唯一合法的异步等待操作符。

yield from 在 Python 异步编程中早已失效
Python 3.5+ 中,yield from 不再是合法的异步协程语法——它只适用于生成器委托,不能替代 await。如果你在 async def 函数里写 yield from some_coro(),会直接报 SyntaxError: 'yield from' inside async function。这不是写法问题,是语言层面禁止的。
旧版基于 yield from 的协程(@asyncio.coroutine)已弃用
Python 3.4 用 @asyncio.coroutine 装饰普通生成器函数,靠 yield from 驱动子协程,例如:
@asyncio.coroutine
def old_style():
result = yield from asyncio.sleep(1, result='done')
return result
这种写法在 Python 3.11 已彻底移除,3.8 起就发 DeprecationWarning。现在调用它会触发 RuntimeWarning: coroutine 'old_style' was never awaited,且无法被 asyncio.run() 正确调度。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
-
yield from本身不创建协程对象,只是生成器语法糖;await才明确要求右侧是Awaitable - 旧式协程返回的是
generator对象,现代协程返回coroutine对象,二者不可混用 -
asyncio.create_task()只接受coroutine,传旧式生成器会报TypeError: a coroutine was expected, got generator
await 和 yield from 的语义与限制完全不同
await 是专用异步等待操作符,强制要求被等待对象实现 __await__ 方法;yield from 是同步生成器的委托机制,哪怕你把它套在协程上调用(如 yield from asyncio.sleep(1)),也只是把协程对象当普通可迭代对象“展开”,根本不会触发调度。
-
await asyncio.sleep(1)→ 进入事件循环等待,释放控制权 -
yield from asyncio.sleep(1)→ 报错(语法不允许),或在非 async 函数中运行 → 返回一个未执行的协程对象,不 await 就等于没调用 -
await支持AsyncIterator、Task、Future等多种 awaitable;yield from只支持实现了__iter__或__getitem__的同步可迭代对象
迁移旧代码时最常踩的坑
把 @asyncio.coroutine + yield from 直接改成 async def + await 看似简单,但有三个隐性雷区:
- 旧代码里可能混用了
yield from asyncio.wait(...),新写法必须改为await asyncio.wait(...),而asyncio.wait()返回的是(done, pending)元组,不是单个结果 - 旧式协程中用
return value会变成StopIteration(value),现代协程中return value是正常返回,但调用方必须用await接收,不能用next()或send() - 第三方库若仍返回旧式生成器协程(比如某些老版本
aiohttp或aioredis),需升级或加一层包装:await asyncio.ensure_future(old_coro())
真正难的不是语法替换,而是确认整个调用链是否已全量切换为现代协程——只要有一处漏掉 await,就会让协程对象悬空,表面无错,实则逻辑不执行。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










