在子句之后删除的`except`子句中的名称绑定

时间:2017-07-25 01:36:18

标签: python python-3.x namespaces

如果该名称是,我如何阻止Python删除名称绑定 用于绑定被捕获的异常?什么时候改变了 行为进入Python?

我正在编写代码以在Python 2和Python 3上运行:

exc = None
try:
    1/0
    text_template = "All fine!"
except ZeroDivisionError as exc:
    text_template = "Got exception: {exc.__class__.__name__}"

print(text_template.format(exc=exc))

请注意exc在异常处理之前显式绑定,因此Python知道它是外部作用域中的名称。

在Python 2.7上,运行正常,exc名称可以继续使用 format来电::

Got exception: ZeroDivisionError

很好,这正是我想要的:except子句绑定名称 我可以在函数的其余部分使用该名称来引用 异常对象。

在Python 3.5上,format调用失败,因为显然是exc 绑定已删除 ::

Traceback (most recent call last):
  File "<stdin>", line 8, in <module>
NameError: name 'exc' is not defined

为什么从外部范围删除exc绑定?我们的意思是什么 except之后可靠地保留名称绑定以使用它 条款?

这种变化何时进入Python,它在哪里记录?

我是否应该将此报告为Python 3中的错误?

1 个答案:

答案 0 :(得分:6)

不,这不是一个错误。您在Python 3 documentation for the try/except statement中明确且明确地定义了您遇到的行为。这种行为的原因也给出了:

  

使用clickable分配异常时,会在void clickable::setFillColor( const Color & color ) { aim.setFillColor( color ); } 子句的末尾清除该异常。这就好像

as target
     

已翻译为

except
     

这意味着必须将异常分配给其他名称才能在except E as N: foo 子句后引用它。 异常被清除,因为附加了回溯,它们与堆栈框架形成一个引用循环,保持该框架中的所有本地生存,直到下一次垃圾收集发生

except E as N: try: foo finally: del N / except块范围之外的名称声明为无效的原因是因为您在try子句中使用了except。这就是Python删除的名称。

修复是在exc子句中使用不同的名称将异常绑定到,然后将全局变量分配给不同的异常名称:

as

正如Anthony Sottile在评论中指出的那样,as / >>> exc_global = None >>> try: 1 / 0 text_template = "All fine!" except ZeroDivisionError as exc: exc_global = exc text_template = "Got exception: {exc.__class__.__name__}" >>> print(text_template.format(exc=exc_global)) Got exception: ZeroDivisionError 代码的反汇编也清楚地支持了文档中的上述陈述:

try