Re-raising exceptions with modified message
samwyse
samwyse at gmail.com
Fri Jul 13 12:53:08 EDT 2007
On Jul 13, 12:45 am, Christoph Zwerschke <c... at online.de> wrote:
> samwyse wrote:
> > TypeError: __class__ must be set to a class
>
> > Excpt ceratinly appears to be a class. Does anyone smarter than me
> > know what's going on here?
>
> Not that I want to appear smarter, but I think the problem here is that
> exceptions are new-style classes now, whereas Empty is an old-style
> class. But even if you define Empty as a new-style class, it will not
> work, you get:
>
> TypeError: __class__ assignment: only for heap types
>
> This tells us that we cannot change the attributes of a built-in
> exception. If it would be possible, I simply would have overridden the
> __str__ method of the original exception in the first place.
>
> -- Chris
Chris, you owe me a beer if you're ever in St. Louis, or I'm ever in
Germany.
# ----- CUT HERE -----
# Written by Sam Denton <samwyse at gmail.com>
# You may use, copy, or distribute this work,
# as long as you give credit to the original author.
# tested successfully under Python 2.4.1, 2.4.3, 2.5.1
"""
On Jul 5, 2007, at 8:53 am, 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.
Here is an example of typical usage:
>>> def typical_usage(code):
... try:
... code()
... except Exception, e:
... simplicity = lambda self: str(e) + ", sorry!"
... raise modify_message(e, simplicity)
Note that if we want to re-cycle the original exception's message,
then we need our re-formatter (here called 'simplicity') to be
defined inside the exception handler. I tried verious approaches
to defining the re-formater, but all of them eventually needed a
closure; I decided that I liked this approach best.
This harness wraps the example so that doctest doesn't get upset.
>>> def test_harness(code):
... try:
... typical_usage(code)
... except Exception, e:
... print "%s: %s" % (e.__class__.__name__, str(e))
Now for some test cases:
>>> test_harness(lambda: 1/0)
ZeroDivisionError: integer division or modulo by zero, sorry!
>>> test_harness(lambda: unicode('\xe4'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position
0: ordinal not in range(128), sorry!
"""
def modify_message(old, f):
"""modify_message(exception, mutator) --> exception
Modifies the string representation of an exception.
"""
class NewStyle(old.__class__):
def __init__(self): pass
NewStyle.__name__ = old.__class__.__name__
NewStyle.__str__ = f
new = NewStyle()
new.__dict__ = old.__dict__.copy()
return new
def _test():
import doctest
return doctest.testmod(verbose=True)
if __name__ == "__main__":
_test()
More information about the Python-list
mailing list