我有一段类似的代码:
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
答案 0 :(得分:106)
空白raise
会引发最后一个异常。
# need to re-raise err so caller can do its own handling
if err:
raise
如果您使用raise something
,Python无法知道something
是否是之前捕获的异常,或者是否有新堆栈跟踪的新异常。这就是保留堆栈跟踪的空白raise
的原因。
答案 1 :(得分:60)
可能modify and rethrow例外:
如果没有表达式,
raise
会重新引发最后一个异常 在当前范围内活跃。如果没有活动的例外 当前范围,引发TypeError
异常,表明这是异常 错误(如果在IDLE下运行,则会引发Queue.Empty
异常 代替)。否则,
raise
使用表达式来计算表达式以获得三个对象None
作为省略表达式的值。前两个对象是 用于确定异常的类型和值。如果存在第三个对象而不是
None
,则它必须是回溯 object(参见标准类型层次结构),它是 替换当前位置而不是当前位置 异常发生。如果第三个对象存在而不是回溯 对象或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]
答案 2 :(得分:5)
您可以通过sys.exc_info()
以及traceback模块获取有关异常的大量信息
尝试对您的代码进行以下扩展。
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
答案 3 :(得分:4)
虽然@Jochen的答案在简单的情况下效果很好,但它不能处理更复杂的情况,你不是直接捕捉和重新抛出,但出于某种原因,将异常作为一个对象和愿望重新投入一个全新的环境(即如果你需要在不同的过程中处理它)。
在这种情况下,我建议如下:
在此之前,请定义一个新的异常类型,稍后您将重新抛出...
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)
答案 4 :(得分:2)
您的主要功能需要如下所示:
def main():
try:
func1()
except Exception, err:
# error processing
raise
这是处理(和重新提出)错误的标准方法。 Here is a codepad demonstration.