python - 如果 name 由 except...as 绑定,为什么 Python 3 会引发 NameError?
问题描述
为什么 Python 3 在NameError
这里提出 a ?名称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
相应的问题。UnboundLocalError
.
解决方案
这是语义上的有意更改,except
以解决在回溯中的帧和帧中的异常之间形成引用循环的问题:
为了解决 PEP 344 相关的垃圾回收问题,Python 3 中的 except 语句会生成额外的字节码来删除目标,从而消除引用循环。正如 Phillip J. Eby [9] 所建议的,源到源的翻译是
try:
try_body
except E as N:
except_body
...
被翻译成(在 Python 2.5 术语中)
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
推荐阅读
- spring - 如何让 STS 4 识别 ~/.bash_profile 文件中定义的环境变量?
- c++ - AprilTag - 以欧拉角形式获取旋转信息
- ruby - 红宝石:TouchAction:move_to
- powershell - PowerShell - 类属性是第二类,但没有为其属性获取任何值
- python - flake8 *修复*我的python空格问题吗?
- c - for循环:在一个循环中进行增量和访问
- angular - Angular:如何从 API 调用响应中提取一个属性?
- kotlin - Kotlin 拳击,看不懂区别?
- php - 需要在php后台运行Curl
- scala - 更新火花数据框中多个火花列的日期格式