如果不立即重新引发,异常回溯将被隐藏

新手上路,请多包涵

我有一段与此类似的代码:

 import sys

def func1():
    func2()

def func2():
    raise Exception('test error')

def main():
    err = None

    try:
        func1()
    except:
        err = sys.exc_info()[1]
        pass

    # some extra processing, involving checking err details (if err is not None)

    # need to re-raise err so caller can do its own handling
    if err:
        raise err

if __name__ == '__main__':
    main()

func2 引发异常时,我收到以下回溯:

 Traceback (most recent call last):
  File "err_test.py", line 25, in <module>
    main()
  File "err_test.py", line 22, in main
    raise err
Exception: test error

从这里我看不到异常来自哪里。原始回溯丢失。

如何保留原始回溯并重新提出?我想看到类似这样的东西:

 Traceback (most recent call last):
  File "err_test.py", line 26, in <module>
    main()
  File "err_test.py", line 13, in main
    func1()
  File "err_test.py", line 4, in func1
    func2()
  File "err_test.py", line 7, in func2
    raise Exception('test error')
Exception: test error

原文由 parxier 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 534
2 个回答

空白 raise 引发最后一个异常。

 # need to re-raise err so caller can do its own handling
if err:
    raise

如果您使用 raise something Python 无法知道 something 是之前刚刚捕获的异常,还是具有新堆栈跟踪的新异常。这就是为什么存在保留堆栈跟踪的空白 raise 的原因。

参考这里

原文由 Jochen Ritzel 发布,翻译遵循 CC BY-SA 3.0 许可协议

可以 修改并重新抛出 异常:

如果不存在表达式, raise 重新引发在当前范围内处于活动状态的最后一个异常。如果当前范围内没有异常活动,则引发 TypeError 异常,表明这是一个错误(如果在 IDLE 下运行,则会引发 Queue.Empty 异常)。

否则, raise 计算表达式以获得三个对象,使用 None 作为省略表达式的值。前两个对象用于确定异常的类型和值。

如果存在第三个对象而不是 None ,则它必须是一个回溯对象(请参阅标准类型层次结构部分),并且它会代替当前位置作为发生异常的位置。如果存在第三个对象并且不是回溯对象或 None ,则会引发 TypeError 异常。

raise 的三表达式形式对于在 except 子句中透明地重新引发异常很有用,但是 raise 如果没有表达式应该是首选重新提出是当前范围内最近活跃的异常。

所以如果你想修改异常并重新抛出,你可以这样做:

 try:
    buggy_code_which_throws_exception()
except Exception as e:
    raise Exception, "The code is buggy: %s" % e, sys.exc_info()[2]

原文由 qris 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题