生成器可通过内部try-except配合throw()构建分层异常处理体系:需在yield处显式捕获异常,按校验层级嵌套try块,用else执行成功逻辑、finally清理资源,并在except中yield而非return以保持生成器可用。

生成器本身不支持传统 try-catch 块(那是语句级语法),但你可以用 生成器函数内部的 try-except 结构,配合 throw() 方法主动注入异常,来构建可响应、可分层、可追溯的复合报错体系。关键不在“单个块”,而在“精准捕获 + 异常传递 + 状态隔离”。
生成器内需主动启用异常接收能力
生成器默认对 throw() 是被动接收的——它不会自动捕获,而是直接中断执行并向上抛出。要优雅处理,必须在生成器函数体中显式写 try-except 包裹可能被 throw() 中断的逻辑段:
-
throw()会像raise一样,在生成器当前暂停点(即最近一个yield)处触发异常 - 只有该
yield所在的try块能捕获它;外层或上一个yield的try不起作用 - 若没写
except,异常直接冒泡,生成器状态变为closed
按校验层级嵌套 try,而非堆砌 except
面对“复合报错体系”(比如:数据格式错误 → 解析失败 → 业务规则冲突),不要在一个 except 里判断类型,而应按校验阶段分层包裹:
- 外层
try:兜底通用异常(如GeneratorExit、SystemExit),做清理或日志 - 中层
try:捕获协议/序列化类异常(如json.JSONDecodeError、UnicodeDecodeError) - 内层
try:捕获业务语义类异常(如ValueError子类InvalidAgeError、MissingFieldError)
这样,当外部调用 gen.throw(BadFormatError("missing key 'id'")) 时,只会触发对应层级的 except,不会干扰其他校验分支。
用 else + finally 明确职责边界
生成器中 else 和 finally 同样生效,且逻辑更清晰:
-
else放“校验通过后才执行的产出逻辑”,比如yield transformed_data,避免在异常路径下误产无效值 -
finally放资源清理(如关闭临时缓冲区、重置状态计数器),注意:若清理操作可能出错,应在finally内再套try-except,防止掩盖主异常
throw 后保持生成器可用的关键细节
想让生成器在 throw() 处理完后继续运行,必须满足两个条件:
- 被
throw()触发的异常在生成器内部被捕获(即有对应except) -
except块末尾不能return或raise新异常(除非你有意终止);推荐用continue或重新yield默认值
例如:except InvalidConfigError: yield {"status": "fallback", "data": []} —— 这样调用方仍可继续 next(gen)。











