生成器默认不处理.throw()异常,因.throw()将异常注入当前yield暂停点,若未用try/except捕获则直接冒泡终止;需将yield置于try块中才能响应。

为什么 generator 默认不处理 .throw() 传入的异常
Python 生成器对象本身支持 .throw() 方法,但如果你没在生成器函数体内显式捕获对应异常,它会直接向上冒泡并终止迭代(抛出 StopIteration 或原异常)。关键点在于:**.throw() 不是“触发”异常,而是“把异常注入当前暂停点”**——就像在 yield 行手动执行了 raise exc。所以,若该位置没 try/except,就等同于在 yield 处未捕获的异常。
在生成器内部用 try/except 捕获 .throw() 注入的异常
必须把 yield 放在 try 块中,并在 except 中决定如何响应。常见做法包括:
- 吞掉异常,继续生成下一项(需再次
yield) - 修改状态后重新抛出(
raise不带参数) - 转换为其他异常再抛出(
raise ValueError("custom") from None) - 直接
return终止生成器(此时.throw()返回值为generator.send()的返回值,即 yield 表达式的值)
示例:
def resilient_gen():
try:
while True:
x = yield "ready"
print(f"got: {x}")
except ValueError as e:
print(f"Caught ValueError: {e}")
yield "recovered"
except GeneratorExit:
print("Generator exiting")
raise # 必须重抛,否则会静默忽略
调用:g = resilient_gen(); next(g); g.throw(ValueError, "boom") → 输出 Caught ValueError: boom,然后产出 "recovered"。
.throw() 的三个参数含义与常见误用
gen.throw(type, value=None, traceback=None) 中:
万通CMS网站管理系统采用PHP+MYSQL技术,支持伪静态功能,可生成google和百度地图,支持自定义url、关键字和描述,利于SEO搜索。拥有企业网站常用的模块功能(企业简介功能、新闻功能、产品功能、下载功能、图片功能、案例功能、在线留言、在线订单、友情链接、网站地图等等),功能强大,操作简单,灵活实用,是企业建站的神兵利器。我们的愿望是:让每个人都能用上 好用,实用,美观的网站,因为建站如
-
type必须是异常类(如ValueError),不能是实例(如ValueError("x"))——否则报TypeError: throw() argument after * must be an exception type or instance -
value可以是异常实例、字符串或None;若为None且type是类,则自动构造type() -
traceback几乎不用,一般留空;手动传入非None值需确保是合法 traceback 对象,否则引发TypeError
错误写法:g.throw(ValueError("bad")) → 报错;正确写法:g.throw(ValueError, "bad") 或 g.throw(ValueError("bad"))(此时第一个参数是实例,跳过类型检查)。
注意 GeneratorExit 和 BaseException 子类的特殊性
.close() 内部调用的就是 .throw(GeneratorExit),而生成器必须传播 GeneratorExit(不能吞掉),否则解释器会强制终止并抛出 RuntimeError。另外,SystemExit、KeyboardInterrupt 等 BaseException 子类默认也不会被 except Exception: 捕获——如果想统一拦截,得写 except BaseException:,但要小心别意外屏蔽掉退出信号。
真正容易被忽略的是:一旦生成器因 .throw() 抛出未捕获异常而结束,后续再调用 .send() 或 .throw() 都会立即引发 StopIteration(Python 3.7+)或 RuntimeError(旧版),无法恢复。









