生成器抛出异常时,是否内部捕获或向外传播取决于其函数体内是否存在匹配的except块:若yield处被try-except包围且能捕获该异常类型,则进入except分支继续执行;否则异常直接向外传播,导致生成器终止并向上冒泡。

生成器抛出异常(通过 throw())时,异常是否在内部被捕获、还是向外传播,取决于生成器函数体内是否存在匹配的 except 块,以及该异常是否被显式处理或重新抛出。关键不在于“谁调用 throw()”,而在于“异常发生在哪个执行点、有没有对应 handler”。
throw() 异常注入的触发位置
调用 gen.throw(exc) 会立即将异常 exc 注入到生成器当前暂停处——也就是上一个 yield 表达式所在的位置。此时生成器尚未执行下一行代码,异常就已在该 yield 点被“抛出”。这相当于:在那个 yield 行插入了一条 raise exc。
- 如果该
yield被包裹在try-except中,且except能捕获该异常类型,则进入except分支 - 如果未被任何
except捕获,异常直接向外传播,由调用throw()的外层代码接收 - 若在
except中执行了raise(无参数)或raise 新异常,则原异常被替换或链式传播
内部捕获的典型结构
生成器需主动设计异常处理逻辑,常见写法是把核心循环或 yield 前后包进 try,并在 except 中做恢复、日志或状态清理:
-
try: value = yield ...—— 这是最常见的捕获点,throw()会在此处中断并跳转至except -
except ValueError:只捕获ValueError及其子类;若传入TypeError,则无法捕获 -
finally:总会执行,适合释放资源(如关闭文件、断开连接)
外部未捕获时的传播表现
当 throw() 注入的异常未被生成器内部处理,它会像普通异常一样向上冒泡:
- 调用方必须用
try-except包裹throw()调用,否则程序崩溃 - 异常类型与原始抛出一致(例如
gen.throw(ValueError("bad"))会抛出ValueError) - 生成器状态变为“已终止”,后续再调用
send()或next()将引发StopIteration
如何验证当前是否被内部捕获
最直接的方式是观察执行流和返回值:
- 若
throw()后生成器继续运行(例如下一次next()成功返回),说明异常已被内部except消化或跳过 - 若
throw()调用本身抛出异常,说明未被内部捕获,传播到了外层 - 在
except块中加print()或日志,可确认是否命中处理分支

















