Python: переопределить __str__ в экземпляре исключения - PullRequest
4 голосов
/ 07 мая 2011

Я пытаюсь переопределить вывод на печать из подкласса Exception в Python после того, как исключение было сгенерировано, и мне не повезло, что мое переопределение было фактически вызвано.почему это на самом деле не отменяет метод str ?Анализ переменных экземпляра показывает, что метод на самом деле переопределен этим методом, но Python просто отказывается вызывать его через print.

Что мне здесь не хватает?

Ответы [ 2 ]

11 голосов
/ 07 мая 2011

Проблема не в том, что __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]

Это динамически выведет новый класс исключений с переопределением str и изменит исключение на экземпляр этого класса.Теперь ваш код должен работать.

2 голосов
/ 07 мая 2011

http://docs.python.org/reference/datamodel.html#special-method-lookup-for-new-style-classes гласит, что «для классов нового стиля неявные вызовы специальных методов гарантированно будут работать правильно только в том случае, если они определены для типа объекта, а не в словаре экземпляров объекта». Я не могу просто присвоить метод some_instance.<strong>__<em>str</em>__</strong>. Кроме того, Monkey Patching не будет работать со встроенными типами, такими как исключения. В любом случае, чего бы вы не хотели, даже для не встроенного класса исключений, поскольку этот патч изменил бы поведение всех экземпляров этого класса.

Если вы чувствуете себя хакером, вы можете вместо этого сделать что-то вроде:

...
except DaUncoolException, e:
    e.args = ('cool override stuff!',) + e.args[1:]
    raise

Мне это не очень нравится. Зачем тебе вообще такое делать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...