如果 name 被 except...as 绑定,为什么 Python 3 会引发 NameError?
Why does Python 3 raise NameError if name is bound by except...as?
为什么Python 3 在这里提出一个NameError
?名称 error
在第一行定义,并在 try...except
块中赋值。这是解释器中的错误,还是我错过了语言定义中从 Python 2 到 3 的细微变化?
error = None
try:
raise Exception('Boom!')
except Exception as error:
pass
if error is not None:
raise error
这是用Python 3.6.7:
执行时的回溯
$ python3 nameerror.py
Traceback (most recent call last):
File "nameerror.py", line 8, in <module>
if error is not None:
NameError: name 'error' is not defined
使用 Python 2.7.15,我们得到预期的 Boom!
:
$ python2 nameerror.py
Traceback (most recent call last):
File "nameerror.py", line 9, in <module>
raise error
Exception: Boom!
如果代码包含在一个函数中,Python 3.6.7 会引发 UnboundLocalError
,而 Python 2.7.15 仍会按预期工作。
$ python3 unbound.py
Traceback (most recent call last):
File "unbound.py", line 13, in <module>
main()
File "unbound.py", line 9, in main
if error is not None:
UnboundLocalError: local variable 'error' referenced before assignment
奇怪的是,从异常处理程序中删除 as error
修复了 NameError
resp。 UnboundLocalError
.
这是 intentional change in the except
semantics 解决的问题,其中在回溯中的帧和帧中的异常之间形成了引用循环:
In order to resolve the garbage collection issue related to PEP 344, except statements in Python 3 will generate additional bytecode to delete the target, thus eliminating the reference cycle. The source-to-source translation, as suggested by Phillip J. Eby [9], is
try:
try_body
except E as N:
except_body
...
gets translated to (in Python 2.5 terms)
try:
try_body
except E, N:
try:
except_body
finally:
N = None
del N
...
您可以简单地通过将其分配给其他名称来保留原始异常,例如:
try:
raise Exception('Boom!')
except Exception as error:
saved_error = error # Use saved_error outside the block
为什么Python 3 在这里提出一个NameError
?名称 error
在第一行定义,并在 try...except
块中赋值。这是解释器中的错误,还是我错过了语言定义中从 Python 2 到 3 的细微变化?
error = None
try:
raise Exception('Boom!')
except Exception as error:
pass
if error is not None:
raise error
这是用Python 3.6.7:
执行时的回溯$ python3 nameerror.py
Traceback (most recent call last):
File "nameerror.py", line 8, in <module>
if error is not None:
NameError: name 'error' is not defined
使用 Python 2.7.15,我们得到预期的 Boom!
:
$ python2 nameerror.py
Traceback (most recent call last):
File "nameerror.py", line 9, in <module>
raise error
Exception: Boom!
如果代码包含在一个函数中,Python 3.6.7 会引发 UnboundLocalError
,而 Python 2.7.15 仍会按预期工作。
$ python3 unbound.py
Traceback (most recent call last):
File "unbound.py", line 13, in <module>
main()
File "unbound.py", line 9, in main
if error is not None:
UnboundLocalError: local variable 'error' referenced before assignment
奇怪的是,从异常处理程序中删除 as error
修复了 NameError
resp。 UnboundLocalError
.
这是 intentional change in the except
semantics 解决的问题,其中在回溯中的帧和帧中的异常之间形成了引用循环:
In order to resolve the garbage collection issue related to PEP 344, except statements in Python 3 will generate additional bytecode to delete the target, thus eliminating the reference cycle. The source-to-source translation, as suggested by Phillip J. Eby [9], is
try:
try_body
except E as N:
except_body
...
gets translated to (in Python 2.5 terms)
try:
try_body
except E, N:
try:
except_body
finally:
N = None
del N
...
您可以简单地通过将其分配给其他名称来保留原始异常,例如:
try:
raise Exception('Boom!')
except Exception as error:
saved_error = error # Use saved_error outside the block