Python:异常装饰器。如何保存堆栈跟踪
我正在编写一个装饰器来应用于函数。它应该捕获任何异常,然后根据原始异常消息引发自定义异常。 (这是因为 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)
I am writing a decorator to apply to a function. It should catch any exception, and then raise a custom exception based on the original exception message. (This is because suds throws a generic WebFault exception, from whose message I parse the exception thrown by the web service and raise a Python exception to mirror it.)
However, when I raise the custom exception in the wrapper, I want the stacktrace to point to the function that raised the original WebFault exception. What I have so far raises the correct exception (it dynamically parses the message and instantiates the exception class). My question: How can I preserve the stacktrace to point to the original function that raised the WebFault exception?
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 Python 2.x 中,
raise
的一个鲜为人知的特性是它可以与多个参数一起使用:raise
的三参数形式接受异常类型、异常实例和回溯。您可以使用 sys.exc_info() 获取回溯,它返回(并非巧合)异常类型、异常实例和回溯。(将异常类型和异常实例视为两个单独的参数的原因是异常类出现之前的产物。)
因此:
在 Python 3 中,这发生了一些变化。在那里,回溯被附加到异常实例,并且它们有一个
with_traceback
方法:另一方面,Python 3 也有异常链接,这在许多方面更有意义案例;要使用它,您只需使用:
In Python 2.x, a little-known feature of
raise
is that it can be used with more than just one argument: the three-argument form ofraise
takes the exception type, the exception instance and the traceback. You can get at the traceback withsys.exc_info()
, which returns (not coincidentally) the exception type, the exception instance and the traceback.(The reason this treats the exception type and the exception instance as two separate arguments is an artifact from the days before exception classes.)
So:
In Python 3, this changed a little. There, the tracebacks are attached to the exception instance instead, and they have a
with_traceback
method:On the other hand Python 3 also has exception chaining, which makes more sense in many cases; to use that, you would just use:
我在用我的自定义装饰器装饰的测试中遇到了这个问题。
我在装饰器主体中使用了以下构造来保留在单元测试输出中打印的原始跟踪:
I've faced this problem with tests that were decorated with my custom decorators.
I used following construct in decorator body to preserve original trace printed in unittests output: