Python:在异常实例中覆盖__str__

Jam*_*mes 4 python string exception

我试图在引发异常后覆盖Python中Exception子类的打印输出,并且我没有运气实际调用我的覆盖.

def str_override(self):
    """
    Override the output with a fixed string
    """

    return "Override!"

def reraise(exception):
    """
    Re-raise an exception and override its output
    """

    exception.__str__ = types.MethodType(str_override, exception, type(exception))

    # Re-raise and remove ourselves from the stack trace.
    raise exception, None, sys.exc_info()[-1]

def test():
    """
    Should output "Override!" Actually outputs "Bah Humbug"
    """
    try:
        try:
            raise Exception("Bah Humbug")
        except Exception, e:
            reraise(e, "Said Scrooge")
    except Exception, e:
        print e
Run Code Online (Sandbox Code Playgroud)

知道为什么这实际上没有覆盖str方法吗?反思实例变量表明该方法实际上已被方法覆盖,但它就像Python一样拒绝通过print调用它.

我在这里错过了什么?

Boa*_*niv 11

问题不在于__str__()没有被覆盖(就像你已经说过的那样),而是str(e)(通过打印无形地调用它)并不总是等同于e.__str__().更具体地说,如果我做对了,str()(和其他特殊方法,如repr()),将不会在实例字典中查找str - 它只会在类字典中查找它.至少对于所谓的新式类(这是Python 3.x IIRC中的唯一类)来说就是这种情况.你可以在这里读更多关于它的内容:

http://mail.python.org/pipermail/python-bugs-list/2005-December/031438.html

如果要更改重新引发的异常的异常错误消息,可以执行以下操作:

def reraise(exception):
    """
    Re-raise an exception and override its output
    """

    exType = type(exception)
    newExType = type(exType.__name__ + "_Override", (exType,), { '__str__': str_override})
    exception.__class__ = newExType

    # Re-raise and remove ourselves from the stack trace.
    raise exception, None, sys.exc_info()[-1]
Run Code Online (Sandbox Code Playgroud)

这将使用str覆盖动态地派生一个新的异常类,并将异常更改为该类的实例.现在你的代码应该工作了.