【问题标题】:Difference between "raise" and "raise e"?“raise”和“raise e”的区别?
【发布时间】:2016-03-22 11:57:45
【问题描述】:

在python中,除了块中的raiseraise 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        

【问题讨论】:

  • raise with no argument的可能重复
  • @Jérôme 我不认为这是重复的。这个问题是关于这个特定代码示例中 no-arg 和 with-arg 版本之间的区别。这个问题是关于无参数通常如何工作的。它们相关但不重复
  • 是的,正是因为这个原因,被接受的答案很有趣。如果有办法取消标记问题,我会这样做。

标签: python exception


【解决方案1】:

两种形式生成的回溯存在差异。

使用raise,此代码:

try:
   int("hello")
except ValueError as e:
   raise

提供以下回溯:

Traceback (most recent call last):
  File "myfile.py", line 2, in <module>
    int("hello")
ValueError: invalid literal for int() with base 10: 'hello'

使用raise e如下:

try:
   int("hello")
except ValueError as e:
   raise e

给出以下回溯

Traceback (most recent call last):
  File "myfile.py", line 4, in <module>
    raise e
ValueError: invalid literal for int() with base 10: 'hello'

不同之处在于,在raise 情况下,引用异常原始源的正确行在回溯中引用,但在raise e 情况下,回溯引用raise e 行而不是原始原因。

因此,我建议始终使用raise 而不是raise e

【讨论】:

  • 您所描述的行为适用于 Python 2,但不适用于 Python 3。在 Python 3 中,raise e 不会吞下原始源代码,而是严格显示 more在这种情况下的信息。
  • 这是非常重要的一点。由于raise e,我花了太多时间来追踪错误的真正来源。
【解决方案2】:

在这种情况下没有区别。 raise 不带参数 will always raise the last exception thrown(也可以通过 sys.exc_info() 访问)。

字节码不同的原因是因为 Python 是一种动态语言,解释器并不真正“知道”e 指的是当前正在处理的(未修改的)异常。但情况可能并非总是如此,请考虑:

try:
    raise Exception()
except Exception as e:
    if foo():
        e = OtherException()
    raise e

e 现在是什么?无法判断何时编译字节码(仅在实际运行程序时)。

在像您这样的简单示例中,Python 解释器可能会“优化”字节码,但到目前为止还没有人这样做。他们为什么要这样做?这充其量只是一个微优化,并且在模糊的条件下仍可能以微妙的方式破坏。还有很多其他的水果比这个挂得低很多,而且更有营养;-)

【讨论】:

    【解决方案3】:

    可以使用sys.exc_clear() 清除“最后一个异常”(即sys.exc_info() 的结果)信息。例如,如果 catch 块调用函数 foo(),就会发生这种情况,该函数本身具有特殊的错误处理。

    在这种情况下,raise 带和不带参数意味着不同的东西。 raise e 仍然会引用上面几行捕获的异常,而 raise 简写会尝试引发 None,这是一个错误。

    【讨论】:

      猜你喜欢
      • 2011-06-15
      • 2013-10-29
      • 2012-06-17
      • 2021-05-15
      • 1970-01-01
      • 2013-12-11
      • 2017-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多