不,这不是错误。在Python 3文档中,针对try
/except
语句明确定义了您所遇到的行为。还给出了此行为的原因:
当使用分配了异常后as target
,该异常将在该except
子句的末尾清除。好像
except E as N:
foo
被翻译成
except E as N:
try:
foo
finally:
del N
这意味着必须将异常分配给其他名称,以便在except
子句之后引用它。 。
在try
/except
块范围之外声明名称无效的原因是因为您exc
在as
子句中使用了该名称。这就是Python删除的名称。
解决方法是在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
正如Anthony Sottile在评论中指出的,try
/except
代码的反汇编也明确支持文档中的上述声明:
>>> code = """
try:
1/0
text_template = "All fine!"
except ZeroDivisionError as exc:
text_template = "Got exception: {exc.__class__.__name__}"
"""
>>> from dis import dis
>>> dis(code)
2 0 SETUP_EXCEPT 16 (to 18)
3 2 LOAD_CONST 0 (1)
4 LOAD_CONST 1 (0)
6 BINARY_TRUE_DIVIDE
8 POP_TOP
4 10 LOAD_CONST 2 ('All fine!')
12 STORE_NAME 0 (text_template)
14 POP_BLOCK
16 JUMP_FORWARD 38 (to 56)
5 >> 18 DUP_TOP
20 LOAD_NAME 1 (ZeroDivisionError)
22 COMPARE_OP 10 (exception match)
24 POP_JUMP_IF_FALSE 54
26 POP_TOP
28 STORE_NAME 2 (exc)
30 POP_TOP
32 SETUP_FINALLY 10 (to 44)
6 34 LOAD_CONST 3 ('Got exception: {exc.__class__.__name__}')
36 STORE_NAME 0 (text_template)
38 POP_BLOCK
40 POP_EXCEPT
42 LOAD_CONST 4 (None)
>> 44 LOAD_CONST 4 (None)
46 STORE_NAME 2 (exc)
48 DELETE_NAME 2 (exc)
50 END_FINALLY
52 JUMP_FORWARD 2 (to 56)
>> 54 END_FINALLY
>> 56 LOAD_CONST 4 (None)
58 RETURN_VALUE