gpt4 book ai didi

Python:异常装饰器。如何保留堆栈跟踪

转载 作者:IT老高 更新时间:2023-10-28 20:50:24 31 4
gpt4 key购买 nike

我正在编写一个装饰器来应用于一个函数。它应该捕获任何异常,然后根据原始异常消息引发自定义异常。 (这是因为 suds 抛出了一个通用的 WebFault 异常,我从它的消息中解析 Web 服务抛出的异常并引发 Python 异常来镜像它。)

但是,当我在包装器中引发自定义异常时,我希望堆栈跟踪指向引发原始 WebFault 异常的函数。到目前为止,我提出了正确的异常(它动态解析消息并实例化异常类)。 我的问题:如何保留堆栈跟踪以指向引发 WebFault 异常的原始函数?

from functools import wraps

def try_except(fn):
def wrapped(*args, **kwargs):
try:
fn(*args, **kwargs)
except Exception, e:
parser = exceptions.ExceptionParser()
raised_exception = parser.get_raised_exception_class_name(e)
exception = getattr(exceptions, raised_exception)
raise exception(parser.get_message(e))
return wraps(fn)(wrapped)

最佳答案

在 Python 2.x 中,raise 的一个鲜为人知的特性是它可以与多个参数一起使用:raise 的三参数形式接受异常类型、异常实例和回溯。您可以使用 sys.exc_info() 获取回溯,它返回(并非巧合)异常类型、异常实例和回溯。

(将异常类型和异常实例视为两个单独的参数的原因是异常类出现之前的产物。)

所以:

import sys

class MyError(Exception):
pass

def try_except(fn):
def wrapped(*args, **kwargs):
try:
return fn(*args, **kwargs)
except Exception, e:
et, ei, tb = sys.exc_info()
raise MyError, MyError(e), tb
return wrapped

def bottom():
1 / 0

@try_except
def middle():
bottom()

def top():
middle()

>>> top()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "tmp.py", line 24, in top
middle()
File "tmp.py", line 10, in wrapped
return fn(*args, **kwargs)
File "tmp.py", line 21, in middle
bottom()
File "tmp.py", line 17, in bottom
1 / 0
__main__.MyError: integer division or modulo by zero

在 Python 3 中,这发生了一些变化。在那里,回溯被附加到异常实例,它们有一个 with_traceback 方法:

raise MyError(e).with_traceback(tb)

另一方面,Python 3 也有异常chaining,这在很多情况下更有意义;要使用它,您只需使用:

raise MyError(e) from e

关于Python:异常装饰器。如何保留堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9005941/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com