简体   繁体   English

Python 使用过滤回溯引发异常

[英]Python Raising Exception with filtered traceback

I'm trying to raise an exception with a stacktrace that doesn't include the last Frame.我正在尝试使用不包含最后一帧的堆栈跟踪引发异常。

In python 2 it was possible to remove the last entry from the strack like this:在 python 2 中,可以像这样从 strack 中删除最后一个条目:

def exceptionCatcher(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception:
            excInfo = sys.exc_info()
            # some custom logging stuff
            raise excInfo[0], excInfo[1], excInfo[2].tb_next
    return wrapper

def a():
    raise Exception("My Exception")

@exceptionCatcher
def test():
    a()

This worked in python and excluded the last exceptionCatcher call itself from the traceback eg这在 python 中有效,并从回溯中排除了最后一个 exceptionCatcher 调用本身,例如

Traceback (most recent call last):
  File "test.py", line 15, in <module>
    test()
  File "test.py", line 12, in a
    raise Exception("a")
Exception: a 

instead of代替

Traceback (most recent call last):
  File "test.py", line 12, in <module>
    test()
  File "test.py", line 9, in wrapper
    raise e
  File "test.py", line 5, in wrapper
    return func(*args, **kwargs)
  File "test.py", line 10, in test
    a()
  File "test.py", line 5, in a
    raise Exception("a")
Exception: a

Switching to python3 it's not possible to raise an exception like: raise excInfo[0], excInfo[1], excInfo[2].tb_next切换到 python3 不可能引发异常,例如: raise excInfo[0], excInfo[1], excInfo[2].tb_next

and i had to use:我不得不使用:

def exceptionCatcher(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            excInfo = sys.exc_info()
            # some custom logging stuff
            raise e.with_traceback(excInfo[2].tb_next)
...  

Which added the following line to my traceback:在我的回溯中添加了以下行:

Traceback (most recent call last):
  File "test.py", line 12, in <module>
    test()
  File "test.py", line 9, in wrapper
    raise e.with_traceback(excInfo[2].tb_next)
  File "test.py", line 10, in test
    a()
  File "test.py", line 5, in a
    raise Exception("a")
Exception: a

Is there any way to get rid of this part of the traceback?有什么办法可以摆脱这部分回溯?

I know exceptionCatching can be done with the exceptionhook but in the scenario i'm using this it's not possible to use the exceptionhook as it's another third party application (in cpp) which seems to catch the exception so the exceptionhook won't catch any.我知道 exceptionCatching 可以用 exceptionhook 完成,但在我使用这个的场景中,不可能使用 exceptionhook,因为它是另一个第三方应用程序(在 cpp 中),它似乎捕获异常,所以 exceptionhook 不会捕获任何异常。 So i came up with the idea of using a wrapper decorator as shown above eventho it's a hacky way.所以我想出了使用包装装饰器的想法,如上所示,尽管这是一种 hacky 方式。

Instead of a decorator, use a context manager, which doesn't add a stack frame in the first place.使用上下文管理器代替装饰器,它首先不添加堆栈框架。

import contextlib


@contextlib.contextmanager
def exceptionCatcher():
    try:
        yield
    except Exception as e:
        print("custom logging")
        raise


def a():
    raise Exception("My Exception")


def test():
    with exceptionCatcher():
        a()


test()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM