python中用来回溯异常的模块_python-如果未立即重新引发异常回溯,则将其隐藏...

python-如果未立即重新引发异常回溯,则将其隐藏

我有一段类似于以下的代码:

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

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

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

5个解决方案

104 votes

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

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

if err:

raise

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

这里参考

Jochen Ritzel answered 2019-10-03T09:41:28Z

59 votes

可以修改并抛出异常:

如果不存在任何表达式,则raise重新引发最后一个例外,即   在当前范围内处于活动状态。 如果没有异常在   当前范围,将引发except异常,表明这是   错误(如果在IDLE下运行,则会引发raise异常   代替)。

否则,raise使用以下方法评估表达式以获取三个对象   except作为省略表达式的值。 前两个对象是   用于确定异常的类型和值。

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

三表达   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 answered 2019-10-03T09:42:30Z

5 votes

您可以通过sys.exc_info()以及回溯模块获得有关该异常的大量信息。

请尝试以下代码扩展。

import sys

import traceback

def func1():

func2()

def func2():

raise Exception('test error')

def main():

try:

func1()

except:

exc_type, exc_value, exc_traceback = sys.exc_info()

# Do your verification using exc_value and exc_traceback

print "*** print_exception:"

traceback.print_exception(exc_type, exc_value, exc_traceback,

limit=3, file=sys.stdout)

if __name__ == '__main__':

main()

这将打印,类似于您想要的。

*** print_exception:

Traceback (most recent call last):

File "err_test.py", line 14, in main

func1()

File "err_test.py", line 5, in func1

func2()

File "err_test.py", line 8, in func2

raise Exception('test error')

Exception: test error

Senthil Kumaran answered 2019-10-03T09:43:08Z

4 votes

尽管@Jochen的答案在简单的情况下效果很好,但它无法处理更复杂的情况,在这种情况下,您不能直接捕获并重新抛出,但由于某种原因被赋予例外,因此希望将其完全抛出 新的上下文(即,如果您需要在其他过程中处理它)。

在这种情况下,我提出以下建议:

得到原始的exc_info

使用堆栈跟踪格式化原始错误消息

引发一个新的异常,内嵌完整的错误消息(包括堆栈跟踪信息)

在执行此操作之前,请定义新的异常类型,稍后将其重新抛出...

class ChildTaskException(Exception):

pass

在令人反感的代码中...

import sys

import traceback

try:

# do something dangerous

except:

error_type, error, tb = sys.exc_info()

error_lines = traceback.format_exception(error_type, error, tb)

error_msg = ''.join(error_lines)

# for example, if you are doing multiprocessing, you might want to send this to another process via a pipe

connection.send(error_msg)

重新投掷...

# again, a multiprocessing example of receiving that message through a pipe

error_msg = pcon.recv()

raise ChildTaskException(error_msg)

tvt173 answered 2019-10-03T09:44:21Z

2 votes

您的主要功能应如下所示:

def main():

try:

func1()

except Exception, err:

# error processing

raise

这是处理(和重新引发)错误的标准方法。 这是一个键盘演示。

Gabi Purcaru answered 2019-10-03T09:44:54Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值