On Thu, May 6, 2010 at 8:50 PM, Ben Cohen <nco...@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 -- http://mail.python.org/mailman/listinfo/python-list