Python生成器函数中StopIteration异常处理报错修复问题
问题根因
- PEP 479规范(Python 3.7及以上版本生效)规定:生成器函数内部主动抛出
StopIteration时,解释器会将其包装为RuntimeError抛出,不会被识别为生成器迭代结束的正常信号。你当前的fibo生成器在n1等于8时主动抛StopIteration,符合该触发场景,因此会抛出RuntimeError。 - 版本1的调用逻辑存在重复取值问题:
for循环遍历生成器时会隐式调用next()获取值赋值给循环变量ele,循环内部又手动调用next(seq),单次循环消耗2个生成器值,因此出现跳数输出、提前耗尽的问题。 - 版本2的异常捕获未生效是因为生成器内部抛出的
StopIteration已经被转成了RuntimeError,不在你的异常捕获范围内,因此触发未捕获报错。
修复方案
步骤1:修正生成器写法
生成器不需要主动抛出StopIteration,自然退出函数/循环即可触发正常的迭代结束信号,修改后的生成器代码如下:
def fibo(): n1 = 0 n2 = 1 while True: if n1 == 8: # 直接结束循环,生成器自然终止,迭代时会抛出正常的StopIteration信号 break yield n1 n1, n2 = n2, n1 + n2 seq = fibo()
步骤2:选择对应调用方式
方式1:for循环遍历(推荐)
不需要手动调用next(),直接打印循环变量即可:
for ele in seq: print(ele)
输出结果为:
0 1 1 2 3 5
完全符合预期。
方式2:while+next手动遍历
生成器修改后,迭代耗尽抛出的是正常的StopIteration信号,原有捕获逻辑可以正常生效:
seq = fibo() # 注意要重新生成生成器实例,避免之前的实例已经耗尽 while True: try: print(next(seq)) except StopIteration: print('This exception is raised in the generator operation defining function. Hence it is handled here.') break
运行后会先打印预期的6个斐波那契数,再触发异常捕获分支打印提示,无RuntimeError。
内容的提问来源于stack exchange,提问作者saint_sharan
相关产品推荐
相关产品推荐

