Python嵌套异常使用同名变量时为何抛出NameError?
Python嵌套try/except中同名异常变量引发NameError的原因与解决方法
问题场景
以下是复现问题的最小示例代码:
try: 1 / 0 except ZeroDivisionError as error: try: [1, 2, 3][3] except IndexError as error: pass print("The last error was:", error)
实际运行后会抛出NameError:
Traceback (most recent call last): File "/home/sorenmulli/lala.py", line 2, in <module> 1 / 0 ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/sorenmulli/lala.py", line 8, in <module> print("The last error was:", error) NameError: name 'error' is not defined
而预期输出应为:
The last error was: list index out of range.
通过以下修改可得到预期结果:
try: 1 / 0 except ZeroDivisionError as error_tmp: error = error_tmp try: [1, 2, 3][3] except IndexError as error_tmp: error = error_tmp print("The last error was:", error)
原因解析
核心原因是:Python在except块执行完毕后,会自动销毁该块内通过as绑定的异常变量。这个设计是为了避免异常对象因被当前栈帧引用而无法被垃圾回收,防止内存泄漏。
具体到你的代码逻辑:
- 外层
except ZeroDivisionError as error:error绑定了除零异常对象,作用域为外层except块。 - 内层触发IndexError后,
except IndexError as error中的error是内层except块的局部变量,会遮蔽外层的error,并重新绑定索引异常对象。 - 内层except块执行完毕,Python自动销毁这个
error变量。由于内层的error已经覆盖了外层的同名变量绑定,后续print语句访问error时,该变量已不存在,因此抛出NameError。
解决方法
你的修正思路是可行的:将异常变量赋值给外层作用域的变量,避开except块的自动销毁机制。另外也可以直接用不同的变量名区分内外层异常,代码可读性更高:
try: 1 / 0 except ZeroDivisionError as outer_err: current_err = outer_err try: [1, 2, 3][3] except IndexError as inner_err: current_err = inner_err print("The last error was:", current_err)
内容的提问来源于stack exchange,提问作者Lombardy
相关产品推荐
相关产品推荐

