Python2与Python3:未定义异常变量[重复]

jv4diomz  于 2022-12-27  发布在  Python
关注(0)|答案(1)|浏览(107)
    • 此问题在此处已有答案**:

except-clause deletes local variable(1个答案)
18小时前关门了。
我在python2(2.7.18)中编写了这个小代码段来捕获变量中的异常,它可以正常工作

>>> ex = None
>>> try:
...   raise Exception("test")
... except Exception as ex:
...   print(ex)
...
test
>>> ex
Exception('test',)
>>>
>>> ex2 = None
>>> try:
...   raise Exception("test")
... except Exception as ex2:
...   print(ex2)
... finally:
...   print(ex2)
...
test
test

当我在python3(3.10.8)中运行相同的命令时,我得到了NameError

>>> ex = None
>>> try:
...   raise Exception("test")
... except Exception as ex:
...   print(ex)
...
test
>>> ex
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'ex' is not defined. Did you mean: 'hex'?
>>>
>>> ex2 = None
>>> try:
...   raise Exception("test")
... except Exception as ex2:
...   print(ex2)
... finally:
...   print(ex2)
...
test
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
NameError: name 'ex2' is not defined

这是什么原因呢?是新的python3编译器在优化None赋值语句,还是try/except子句在变魔术?
在python2和python3中都有效的解决方法是什么?

8i9zcol2

8i9zcol21#

其实这不是魔术。它记录在这里:
当使用as target分配异常时,它将在except子句的末尾被清除。这就好比:

except E as N:
    foo

被翻译成

except E as N:
    try:
        foo
    finally:
        del N

原因是:
异常被清除是因为它们附加了回溯,它们与堆栈帧形成了一个引用循环,使该帧中的所有局部变量保持活动状态,直到下一次垃圾回收发生。
您可以使用ex.__traceback__获取traceback对象。
在python2和python3中都有效的解决方法是什么?
你必须显式地给它指定一个不同的名字(在as target中不是target的名字,因为它会被删除):

exc_object = None

try:
    raise Exception("test")
except Exception as ex:
    print(ex)
    exc_object = ex

print(exc_object)

**注意:**这只是except块的情况,与as赋值语句无关,正如您在上下文管理器中看到的:例如with...as...块。

相关问题