Python except子句删除局部变量

Python except子句删除局部变量,python,python-3.x,scope,try-except,Python,Python 3.x,Scope,Try Except,NameError:未定义名称“exc” 这曾经在Python2中起作用。为什么会这样改变呢?如果我至少可以重新分配给exc,类似于类级属性 exc = None try: raise Exception except Exception as exc: pass # ... print(exc) 但这也不能让它起作用: class Foo(object): Bar = Bar 有什么好的提示可以达到同样的效果吗?我不想写这样的东西: exc = None try

NameError:未定义名称“exc”

这曾经在Python2中起作用。为什么会这样改变呢?如果我至少可以重新分配给
exc
,类似于类级属性

exc = None
try:
    raise Exception
except Exception as exc:
    pass

# ...

print(exc)
但这也不能让它起作用:

class Foo(object):
    Bar = Bar
有什么好的提示可以达到同样的效果吗?我不想写这样的东西:

exc = None
try:
    raise Exception
except Exception as exc:
    exc = exc

try
语句明确限制绑定异常的范围,以防止循环引用导致其泄漏。见:

当使用as target分配异常时,将在except子句末尾清除该异常

[……]

这意味着必须将异常指定给不同的名称,才能在except子句之后引用它。异常会被清除,因为通过附加到它们的回溯,它们与堆栈帧形成一个引用循环,使该帧中的所有局部变量保持活动状态,直到下一次垃圾回收发生

重点矿山;请注意,您唯一的选择是将异常绑定到新名称

在Python2中,异常没有对回溯的引用,这就是为什么要更改它

但是,即使在Python 2中,也会明确警告您清理回溯,请参阅:

警告:将回溯返回值指定给处理异常的函数中的局部变量将导致循环引用。这将防止同一函数中的局部变量或回溯引用的任何内容被垃圾收集。由于大多数函数不需要访问回溯,因此最好的解决方案是使用类似于
exctype,value=sys.exc_info()[:2]
的方法来仅提取异常类型和值。如果确实需要回溯,请确保在使用后将其删除(最好使用
try…finally
语句),或者在本身不处理异常的函数中调用
exc_info()

如果确实重新绑定了异常,则可能需要显式清除回溯:

exc = None
try:
    raise Exception("foo")
except Exception as e:
    exc = e

# ...

print(exc)
try:
    raise Exception("foo")
except Exception as e:
    exc = e
    exc.__traceback__ = None