Re-raising exceptions with modified message

Kay Schluehr kay.schluehr at gmx.net
Thu Jul 5 16:40:29 EDT 2007


On Jul 5, 3:53 pm, Christoph Zwerschke <c... at online.de> wrote:
> What is the best way to re-raise any exception with a message
> supplemented with additional information (e.g. line number in a
> template)? Let's say for simplicity I just want to add "sorry" to every
> exception message. My naive solution was this:
>
> try:
>      ...
> except Exception, e:
>      raise e.__class__, str(e) + ", sorry!"
>
> This works pretty well for most exceptions, e.g.
>
>  >>> try:
> ...     1/0
> ... except Exception, e:
> ...     raise e.__class__, str(e) + ", sorry!"
> ...
> Traceback (most recent call last):
>    File "<stdin>", line 4, in <module>
> ZeroDivisionError: integer division or modulo by zero, sorry!
>
> But it fails for some exceptions that cannot be instantiated with a
> single string argument, like UnicodeDecodeError which gets "converted"
> to a TypeError:
>
>  >>> try:
> ...     unicode('\xe4')
> ... except Exception, e:
> ...     raise e.__class__, str(e) + ", sorry!"
> ...
> Traceback (most recent call last):
>    File "<stdin>", line 4, in <module>
> TypeError: function takes exactly 5 arguments (1 given)
>
> Another approach is using a wrapper Extension class:
>
> class SorryEx(Exception):
>      def __init__(self, e):
>          self._e = e
>      def __getattr__(self, name):
>          return getattr(self._e, name)
>      def __str__(self):
>          return str(self._e) + ", sorry!"
>
> try:
>      unicode('\xe4')
> except Exception, e:
>      raise SorryEx(e)
>
> But then I get the name of the wrapper class in the message:
>
> __main__.SorryEx: 'ascii' codec can't decode byte 0xe4 in position 0:
> ordinal not in range(128), sorry!
>
> Yet another approach would be to replace the __str__ method of e, but
> this does not work for new style Exceptions (Python 2.5).
>
> Any suggestions?
>
> -- Chris

If you are sure that the exception isn't caught on another level just
use the following showtraceback() function, manipulate it's output
slightly and terminate your program with sys.exit()

    def showtraceback():
        '''
        (Copied from code.py)
        '''
        try:
            type, value, tb = sys.exc_info()
            sys.last_type = type
            sys.last_value = value
            sys.last_traceback = tb
            tblist = traceback.extract_tb(tb)
            del tblist[:1]
            lst = traceback.format_list(tblist)
            if lst:
                lst.insert(0, "Traceback (most recent call last):\n")
            lst[len(lst):] = traceback.format_exception_only(type,
value)
        finally:
            tblist = tb = None
        sys.stderr.write("".join(lst))





More information about the Python-list mailing list