exc = None
try:
raise Exception
except Exception as exc:
pass
# ...
print(exc)
NameError:name' exc'未定义
这曾经在Python2中工作。为什么这样改变了?如果我至少可以重新分配给exc
,则类似于类级属性
class Foo(object):
Bar = Bar
但是这也没有成功:
exc = None
try:
raise Exception
except Exception as exc:
exc = exc
有什么好的提示可以实现同样的目标吗?我不想写这样的东西:
exc = None
try:
raise Exception("foo")
except Exception as e:
exc = e
# ...
print(exc)
答案 0 :(得分:7)
try
语句明确限制了绑定异常的范围,以防止导致其泄漏的循环引用。请参阅try
statement documentation:
当使用as作为目标分配例外时,会在except子句的末尾清除它。
[...]
这意味着必须将异常分配给其他名称才能在except子句之后引用它。异常被清除,因为附加了回溯,它们与堆栈帧形成一个引用循环,使该帧中的所有本地生存,直到下一次垃圾收集发生。
强调我的;请注意, only选项是将异常绑定到新名称。
在Python 2中,异常没有对回溯的引用,这就是为什么改变它的原因。
但是,即使在Python 2中,也明确警告您要清理回溯,请参阅sys.exc_info()
:
警告:将 traceback 返回值分配给处理异常的函数中的局部变量将导致循环引用。这将阻止同一函数中的局部变量或回溯引用的任何内容被垃圾回收。由于大多数函数不需要访问回溯,因此最好的解决方案是使用
exctype, value = sys.exc_info()[:2]
之类的东西来仅提取异常类型和值。如果确实需要回溯,请确保在使用后删除它(最好使用try ... finally
语句)或在本身不处理异常的函数中调用exc_info()
。
如果确实重新绑定了异常,则可能需要明确清除回溯:
try:
raise Exception("foo")
except Exception as e:
exc = e
exc.__traceback__ = None