idiomatic way to collect and report multiple exceptions?
Chris Rebert
crebert at ucsd.edu
Fri May 7 00:56:10 EDT 2010
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