在Python,有之间的差raise和raise e在除块?
dis 向我展示了不同的结果,但我不知道这意味着什么.
两者的最终行为是什么?
import dis
def a():
try:
raise Exception()
except Exception as e:
raise
def b():
try:
raise Exception()
except Exception as e:
raise e
dis.dis(a)
# OUT: 4 0 SETUP_EXCEPT 13 (to 16)
# OUT: 5 3 LOAD_GLOBAL 0 (Exception)
# OUT: 6 CALL_FUNCTION 0
# OUT: 9 RAISE_VARARGS 1
# OUT: 12 POP_BLOCK
# OUT: 13 JUMP_FORWARD 22 (to 38)
# OUT: 6 >> 16 DUP_TOP
# OUT: 17 LOAD_GLOBAL 0 (Exception)
# OUT: 20 COMPARE_OP 10 (exception match)
# OUT: 23 POP_JUMP_IF_FALSE 37
# OUT: 26 POP_TOP
# OUT: 27 STORE_FAST 0 (e)
# OUT: 30 POP_TOP
# OUT: 7 31 RAISE_VARARGS 0
# OUT: 34 JUMP_FORWARD 1 (to 38)
# OUT: >> 37 END_FINALLY
# OUT: >> 38 LOAD_CONST 0 (None)
# OUT: 41 RETURN_VALUE
dis.dis(b)
# OUT: 4 0 SETUP_EXCEPT 13 (to 16)
# OUT: 5 3 LOAD_GLOBAL 0 (Exception)
# OUT: 6 CALL_FUNCTION 0
# OUT: 9 RAISE_VARARGS 1
# OUT: 12 POP_BLOCK
# OUT: 13 JUMP_FORWARD 25 (to 41)
# OUT: 6 >> 16 DUP_TOP
# OUT: 17 LOAD_GLOBAL 0 (Exception)
# OUT: 20 COMPARE_OP 10 (exception match)
# OUT: 23 POP_JUMP_IF_FALSE 40
# OUT: 26 POP_TOP
# OUT: 27 STORE_FAST 0 (e)
# OUT: 30 POP_TOP
# OUT: 7 31 LOAD_FAST 0 (e)
# OUT: 34 RAISE_VARARGS 1
# OUT: 37 JUMP_FORWARD 1 (to 41)
# OUT: >> 40 END_FINALLY
# OUT: >> 41 LOAD_CONST 0 (None)
# OUT: 44 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
Mar*_*oij 18
这种情况没有区别.raise没有参数将始终引发抛出的最后一个异常(也可以访问sys.exc_info()).
字节码不同的原因是因为Python是一种动态语言,并且解释器并不真正"知道" e引用当前正在处理的(未修改的)异常.但情况可能并非总是如此,请考虑:
try:
raise Exception()
except Exception as e:
if foo():
e = OtherException()
raise e
Run Code Online (Sandbox Code Playgroud)
e现在是什么?编译字节码时无法判断(仅在实际运行程序时).
在像你这样的简单示例中,Python解释器可能会"优化"字节码,但到目前为止还没有人这样做过.他们为什么要这样?它充其量只是微观优化,并且在模糊的条件下仍可能以微妙的方式打破.还有很多其他水果比这更低,并且开胃更有营养;-)
小智 16
两种形式产生的回溯有所不同.
使用raise,这段代码:
try:
int("hello")
except ValueError as e:
raise
Run Code Online (Sandbox Code Playgroud)
给出以下回溯:
Traceback (most recent call last):
File "myfile.py", line 2, in <module>
int("hello")
ValueError: invalid literal for int() with base 10: 'hello'
Run Code Online (Sandbox Code Playgroud)
使用raise e方法如下:
try:
int("hello")
except ValueError as e:
raise e
Run Code Online (Sandbox Code Playgroud)
给出以下回溯
Traceback (most recent call last):
File "myfile.py", line 4, in <module>
raise e
ValueError: invalid literal for int() with base 10: 'hello'
Run Code Online (Sandbox Code Playgroud)
区别在于,在这种raise情况下,引用异常的原始源的正确行在引用中被引用,但是在raise e回溯引用该raise e行而不是原始原因的情况下.
因此,我建议总是使用raise而不是raise e.
| 归档时间: |
|
| 查看次数: |
6324 次 |
| 最近记录: |