idiomatic way to collect and report multiple exceptions?
Ben Cohen
ncohen at ucsd.edu
Fri May 7 21:06:43 EDT 2010
Many thanks for the excellent example!! You rock!
Ben
On May 6, 2010, at 10:56 PM, Chris Rebert wrote:
> On Thu, May 6, 2010 at 8:50 PM, Ben Cohen <ncohen at ucsd.edu> wrote:
>> Is there a pythonic way to collect and display multiple exceptions at the same time?
>>
>> For example let's say you're trying to validate the elements of a list and you'd like to validate as many of the elements as possible in one run and still report exception's raised while validating a failed element.
>>
>> eg -- I'd like to do something like this:
>>
>> errors = []
>> for item in data:
>> try:
>> process(item)
>> except ValidationError as e:
>> errors.append(e)
>> raise MultipleValidationErrors(*errors)
>>
>> where if the raised MultipleValidationErrors exception goes uncaught the interpreter will print a nice traceback that includes the tracebacks of each raised ValidationError. But I don't know how MultipleValidationErrors should be written ...
>
> import sys, traceback
>
> def _traceback_for(exc_info):
> return ''.join(traceback.format_exception(*exc_info))
>
> # StandardError can obviously be replaced with
> # whatever exception superclass you want.
> class MultipleValidationErrors(StandardError):
> def __init__(self, errors=None):
> self.errors = errors or []
>
> def __str__(self):
> tracebacks = "\n\n".join(_traceback_for(exc_info) for exc_info in \
> self.errors)
> parts=("See the following exception tracebacks:", "="*78, tracebacks)
> msg = '\n'.join(parts)
> return msg
>
> def capture_current_exception(self):
> self.errors.append(sys.exc_info())
>
> def do_raise(self):
> """Raises itself if it contains any errors"""
> if self.errors:
> raise self
>
>
> #Example usage:
> multiple_err = MultipleValidationErrors()
> for c in "hello":
> try:
> int(c) # obviously fails
> except ValueError: # whatever error type you care about
> multiple_err.capture_current_exception()
> multiple_err.do_raise()
>
>
> Output from example:
> Traceback (most recent call last):
> File "tmp.py", line 35, in <module>
> multiple_err.do_raise()
> File "tmp.py", line 25, in do_raise
> raise self
> __main__.MultipleValidationErrors: See the following exception tracebacks:
> ==============================================================================
> Traceback (most recent call last):
> File "tmp.py", line 32, in <module>
> int(c) # obviously fails
> ValueError: invalid literal for int() with base 10: 'h'
>
>
> Traceback (most recent call last):
> File "tmp.py", line 32, in <module>
> int(c) # obviously fails
> ValueError: invalid literal for int() with base 10: 'e'
>
>
> Traceback (most recent call last):
> File "tmp.py", line 32, in <module>
> int(c) # obviously fails
> ValueError: invalid literal for int() with base 10: 'l'
>
>
> Traceback (most recent call last):
> File "tmp.py", line 32, in <module>
> int(c) # obviously fails
> ValueError: invalid literal for int() with base 10: 'l'
>
>
> Traceback (most recent call last):
> File "tmp.py", line 32, in <module>
> int(c) # obviously fails
> ValueError: invalid literal for int() with base 10: 'o'
>
>
> Cheers,
> Chris
> --
> Go Tritons!
> http://blog.rebertia.com
More information about the Python-list
mailing list