我遇到了一个嵌套try
/except
语句的情况,我不理解Python解释器的行为。
下面是一个与我的用例(连接错误)等效的最小、可重复的示例:
try:
1 / 0
except ZeroDivisionError as error:
try:
[1, 2, 3][3]
except IndexError as error:
pass
print("The last error was:", error)
此示例具有以下输出
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)
但在我看来这很奇怪为什么有必要这样做?第二次赋值给error
是否应该覆盖第一次赋值:为什么它会完全删除变量?
- 我使用的是Python 3.9.16,但是我认为输出在Python 3版本之间是一致的。
2条答案
按热度按时间uelo1irk1#
此处记录了该行为。
当使用
as
目标分配异常时,它将在except
子句的末尾被清除。被翻译成
这意味着必须将异常分配给不同的名称,以便能够在
except
子句之后引用它。异常被清除是因为它们附加了跟踪,它们与堆栈帧形成了一个引用循环,使该帧中的所有局部变量保持活动状态,直到下一次垃圾回收发生。因此,在您的代码中,
error
将在except IndexError as error
块的末尾被清除。gzszwxb42#
第二个错误赋值是否应该覆盖第一个错误赋值:为什么它会完全删除变量?
是的,
error
变量在内部try-except块中被覆盖,之后一旦我们离开内部块,它就会被删除。这里Python只是遵循了简单的规则,对try-except块作用域之外的变量进行解引用,但是它也影响了外部块,因为变量是相同的。
试着运行这段代码,你会看到
error
变量有两个不同的ID。一个ID在第一个try-except块中,另一个ID在内部try-except块中。另一件事是你的print语句落在内部try-except块之外,所以在Python解释器到达
print("The last error was:", error)
行之前,内部try-except块已经完成,因此error
变量和NameError异常被删除。在您描述的第二段代码中,它工作正常,因为您复制了对
error
变量中对象的引用,所以当删除error_tmp
时,您仍然使用error
变量引用异常对象。