然而,当我在包装器中引发自定义异常时,我希望stacktrace指向引发原始WebFault异常的函数。到目前为止,我已经提出了正确的异常(动态解析消息并实例化异常类)。 我的问题:如何保留堆栈跟踪指向引发WebFault异常的原始功能?
从functools导入包裹 def try_except(fn): def wrapped(* args,** kwargs): try: fn(* args, ** kwargs)除了异常,e: parser = exceptions.ExceptionParser() raise_exception = parser.get_raised_exception_class_name(e) exception = getattr(exceptions,raise_exception) raise exception(parser.get_message(e)) return wrap(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)除了异常,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()追溯(最近的最后一次调用):文件< stdin>,第1行,< module> 文件tmp.py,第24行,顶部 middle()文件tmp.py,第10行,包装 return fn(* args,* * kwargs)文件tmp.py,第21行,中间 bottom()文件tmp.py,第17行,底部 1/0 __main __。MyError:整数除或模数为零在Python 3中,这改变了一点。在那里,追溯附加到异常实例,而且它们有一个 with_traceback 方法:
raise MyError(e).with_traceback(tb)另一方面Python 3也有例外链接,这在许多情况下更有意义;要使用它,您只需使用:
从e 中提取MyError(e)$ / code >
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)解决方案
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 of raise takes the exception type, the exception instance and the traceback. You can get at the traceback with sys.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:
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 zeroIn Python 3, this changed a little. There, the tracebacks are attached to the exception instance instead, and they have a with_traceback method:
raise MyError(e).with_traceback(tb)On the other hand Python 3 also has exception chaining, which makes more sense in many cases; to use that, you would just use:
raise MyError(e) from e
更多推荐
Python:异常装饰器。如何保留堆栈跟踪
发布评论