par*_*ier 65 python exception-handling exception try-catch traceback
我有一段类似于此的代码:
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()
Run Code Online (Sandbox Code Playgroud)
当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
Run Code Online (Sandbox Code Playgroud)
从这里我看不出异常的来源.原始追溯丢失了.
如何保留原始追溯并重新提升?我想看到类似的东西:
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
Run Code Online (Sandbox Code Playgroud)
Joc*_*zel 110
空白raise会引发最后一个异常.
# need to re-raise err so caller can do its own handling
if err:
raise
Run Code Online (Sandbox Code Playgroud)
如果您使用raise somethingPython无法知道是否something是之前捕获的异常,或者是新堆栈跟踪的新异常.这就是为什么有空白raise来保留堆栈跟踪.
qri*_*ris 66
可以修改和重新抛出异常:
如果不存在表达式,则
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]
Run Code Online (Sandbox Code Playgroud)
您可以通过得到很多关于异常的信息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()
Run Code Online (Sandbox Code Playgroud)
这将打印,类似于您想要的.
*** 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
Run Code Online (Sandbox Code Playgroud)
虽然@Jochen的答案在简单的情况下效果很好,但它无法处理更复杂的情况,在这种情况下,您不能直接捕获并重新抛出,但是由于某种原因被赋予例外,因此希望将其完全抛出新的上下文(即,如果您需要在其他过程中处理它)。
在这种情况下,我提出以下建议:
在执行此操作之前,请定义新的异常类型,稍后将其重新抛出...
class ChildTaskException(Exception):
pass
Run Code Online (Sandbox Code Playgroud)
在令人反感的代码中...
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)
Run Code Online (Sandbox Code Playgroud)
重新投掷...
# again, a multiprocessing example of receiving that message through a pipe
error_msg = pcon.recv()
raise ChildTaskException(error_msg)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
31129 次 |
| 最近记录: |