"except Foo as bar" 导致 "bar" 从范围中删除
"except Foo as bar" causes "bar" to be removed from scope
给定以下代码:
msg = "test"
try:
"a"[1]
except IndexError as msg:
print("Error happened")
print(msg)
有人可以解释为什么这会导致 Python 3 中出现以下输出吗?
Error happened
Traceback (most recent call last):
File "test.py", line 6, in <module>
print(msg)
NameError: name 'msg' is not defined
是的,一旦引发异常并为 msg
分配新的异常对象,原始对象将不再有引用,因此将被删除。新的异常对象也会在离开 except
块后立即被删除。
你可以通过覆盖对象的__del__
方法和分配给msg
的异常来验证它:
class A:
def __del__(self):
print('object deleted')
class E(Exception):
def __del__(self):
print('exception deleted')
msg = A()
try:
raise E()
except E as msg:
print("Error happened")
这输出:
object deleted
Error happened
exception deleted
NameError: name 'msg' is not defined
except 子句中的 msg
与第一行的 msg
在同一范围内。
但是in Python 3 we have this new behavior too:
When an exception has been assigned using as target
, it is cleared at
the end of the except clause. This is as if
except E as N:
foo
was translated to
except E as N:
try:
foo
finally:
del N
This means the exception must be assigned to a different name to be
able to refer to it after the except clause. Exceptions are cleared
because with the traceback attached to them, they form a reference
cycle with the stack frame, keeping all locals in that frame alive
until the next garbage collection occurs.
因此,您 "overwrite msg
" 在异常处理程序中,退出处理程序将删除变量以清除回溯引用循环。
异常块在块的末尾删除捕获的变量,但它们没有自己的作用域。所以事件的顺序是:
1) msg
设置为局部范围内的某个字符串
2) msg
被设置为与 1
在同一本地范围内的 IndexError 对象
3) msg
在 Exception 块结束时从局部作用域中删除
4) msg
不再在本地范围内定义,因此访问它的尝试失败
给定以下代码:
msg = "test"
try:
"a"[1]
except IndexError as msg:
print("Error happened")
print(msg)
有人可以解释为什么这会导致 Python 3 中出现以下输出吗?
Error happened
Traceback (most recent call last):
File "test.py", line 6, in <module>
print(msg)
NameError: name 'msg' is not defined
是的,一旦引发异常并为 msg
分配新的异常对象,原始对象将不再有引用,因此将被删除。新的异常对象也会在离开 except
块后立即被删除。
你可以通过覆盖对象的__del__
方法和分配给msg
的异常来验证它:
class A:
def __del__(self):
print('object deleted')
class E(Exception):
def __del__(self):
print('exception deleted')
msg = A()
try:
raise E()
except E as msg:
print("Error happened")
这输出:
object deleted
Error happened
exception deleted
NameError: name 'msg' is not defined
msg
与第一行的 msg
在同一范围内。
但是in Python 3 we have this new behavior too:
When an exception has been assigned using
as target
, it is cleared at the end of the except clause. This is as ifexcept E as N: foo
was translated to
except E as N: try: foo finally: del N
This means the exception must be assigned to a different name to be able to refer to it after the except clause. Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.
因此,您 "overwrite msg
" 在异常处理程序中,退出处理程序将删除变量以清除回溯引用循环。
异常块在块的末尾删除捕获的变量,但它们没有自己的作用域。所以事件的顺序是:
1) msg
设置为局部范围内的某个字符串
2) msg
被设置为与 1
3) msg
在 Exception 块结束时从局部作用域中删除
4) msg
不再在本地范围内定义,因此访问它的尝试失败