Consider the following common exception handling idiom: def func(iterable): it = iter(iterable) try: x = next(it) except StopIteration: raise ValueError("can't process empty iterable") print(x)
The intention is: * detect an empty iterator by catching StopIteration; * if the iterator is empty, raise a ValueError; * otherwise process the iterator. Note that StopIteration is an internal detail of no relevance whatsoever to the caller. Expose this is unnecessary at best and confusing at worst. In Python 2.6 this idiom works as intended: >>> func([]) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in func ValueError: can't process empty iterable There is no sign of the StopIteration, and nor should there be. But Python 3.1 changes this behaviour, exposing the unimportant StopIteration and leading to a more complicated and confusing traceback: >>> func([]) Traceback (most recent call last): File "<stdin>", line 4, in func StopIteration During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in func ValueError: can't process empty iterable I understand the rational of this approach -- it is to assist in debugging code where the except block is buggy and raises an error. But a deliberate and explicit call to raise is not a buggy except block. It is terribly inappropriate for the common use-case of catching one exception and substituting another. I note that the PEP explicitly notes this use-case, but merely sweeps it under the carpet: Open Issue: Suppressing Context As written, this PEP makes it impossible to suppress '__context__', since setting exc.__context__ to None in an 'except' or 'finally' clause will only result in it being set again when exc is raised. http://www.python.org/dev/peps/pep-3134/ Apart from this horrible idiom: def func(iterable): it = iter(iterable) failed = False try: x = next(it) except StopIteration: failed = True if failed: raise ValueError("can't process empty iterable") print(x) or similar, is there really no way to avoid these chained exceptions? -- Steven -- http://mail.python.org/mailman/listinfo/python-list