简体   繁体   English

如何更改 Python 中自定义异常的回溯?

[英]How to change the traceback of a custom Exception in Python?

I'm trying to create a custom exception that is raised inside of a class. However, whenever I raise it, the traceback leads to the original 'raise' statement.我正在尝试创建一个在 class 内部引发的自定义异常。但是,每当我引发它时,回溯都会导致原始的“引发”语句。

Here's a simplified example of what I'm trying to do这是我正在尝试做的一个简化示例

# Errors
class NotImplementedError(Exception):
    def __init__(self, msg=""):
        super().__init__(msg)

class ImplementationError(Exception):
    def __init__(self, msg):
        super().__init__(msg)
        
# Interface decorator class
class Interface:
    def __init__(self, cls):
        self.cls = cls

    def __call__(self):
        return self.cls()

def implement(interface):
    if type(interface) != Interface:
        raise ImplementationError("Expected interface")
    
    interface = interface.cls

    def wrapper(cls):
        iKeys = interface.__dict__.keys()
        cKeys = cls.__dict__.keys()

        for iKey in iKeys:
            if iKey not in cKeys:
                msg = (f"'{iKey}' not implemented in {cls.__name__}")
                raise NotImplementedError(msg)
        
        return cls

    return wrapper

@Interface
class Shape:
    origin = None

    def area(self): pass
    def bounding_rect(self): pass

@implement(Shape)
class Square:
    pass

And this is the output这是 output

Traceback (most recent call last):
  File "main.py", line 48, in <module>
    class Square:
  File "main.py", line 34, in wrapper
    raise NotImplementedError(msg)
__main__.NotImplementedError: 'origin' not implemented in Square

Instead of the traceback leading to line 8, I want it to only lead to line 14 like this:而不是通向第 8 行的回溯,我希望它只通向第 14 行,如下所示:

Traceback (most recent call last):
  File "main.py", line 48, in <module>
    class Square:
__main__.NotImplementedError: 'origin' not implemented in Square

Is this possible?这可能吗?

I tried googling it and didn't find anything helpful.我试着用谷歌搜索它,但没有找到任何有用的东西。

Edit: I would also like to get rid of the __main__.编辑:我也想摆脱__main__. in the last line of the stack trace if possible.如果可能,在堆栈跟踪的最后一行。

I found an answer (though not very elegant)我找到了答案(虽然不是很优雅)

try:
    raise ImplementationError("Expected interface")
except ImplementationError as e:
    frame = e.__traceback__.tb_frame.f_back
    tb = e.__traceback__.__class__(None, frame, frame.f_lasti, frame.f_lineno)

    traceback.print_exception(e, e, tb)
    exit()

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

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