Skip to content

Commit

Permalink
PEP 654: Add section about handling ExceptionGroups (#1841)
Browse files Browse the repository at this point in the history
  • Loading branch information
iritkatriel authored Feb 26, 2021
1 parent e93b2ef commit d729120
Showing 1 changed file with 55 additions and 12 deletions.
67 changes: 55 additions & 12 deletions pep-0654.rst
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,47 @@ in the following example:
ValueError: 1
>>>
Handling ``ExceptionGroups``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

We expect that when programs catch and handle ``ExceptionGroups``, they will
typically either query to check if it has leaf exceptions for which some
condition holds (using ``subgroup`` or ``split``) or format the exception
(using the ``traceback`` module's methods).

It is unlikely to be useful to inspect the individual leaf exceptions. To see
why, suppose that an application caught an ``ExceptionGroup`` raised in an
``asyncio.gather()`` call. At this stage, the context for each specific
exception is lost. Any recovery for this exception should have been performed
before it was grouped with other exceptions into the ``ExceptionGroup`` [10]_.
Furthermore, the application is likely to react in the same way to any number
of instances of a certain exception type, so it is more likely that we will
want to know whether ``eg.subgroup(T)`` is None or not, than we are to be
intersted in the number of ``Ts`` in ``eg``.

If it does turn out to be necessary for an applicaiton to iterate over the
individual exceptions of an ``ExceptionGroup`` ``eg``, this can be done by
calling ``traverse(eg)``, where ``traverse`` is defined as follows:

.. code-block::
def traverse(exc, tbs=None, cause=None, context=None):
if tbs is None:
tbs = []
cause = exc.__cause__
context = exc.__context__
tbs.append(exc.__traceback__)
if isinstance(exc, ExceptionGroup):
for e in exc.errors:
traverse(e, tbs, cause, context)
else:
# exc is a leaf exception and its traceback
# is the concatenation of the traceback in tbs
process_leaf(exc, tbs, cause, context)
tbs.pop()
except*
-------

Expand Down Expand Up @@ -930,7 +971,7 @@ Reference Implementation
========================

We developed these concepts (and the examples for this PEP) with
the help of the reference implementation [10]_.
the help of the reference implementation [11]_.

It has the builtin ``ExceptionGroup`` along with the changes to the traceback
formatting code, in addition to the grammar, compiler and interpreter changes
Expand All @@ -951,18 +992,20 @@ metadata as the original, while the raised ones do not.
Rejected Ideas
==============

The ExceptionGroup API
----------------------
Make ExceptionGroup Iterable
----------------------------

We considered making ``ExceptionGroups`` iterable, so that ``list(eg)`` would
produce a flattened list of the leaf exceptions contained in the group.
We decided that this would not be not be a sound API, because the metadata
We decided that this would not be a sound API, because the metadata
(cause, context and traceback) of the individual exceptions in a group is
incomplete and this could create problems. If use cases arise where this
can be helpful, we can document (or even provide in the standard library)
a sound recipe for accessing an individual exception: use the ``split()``
method to create an ``ExceptionGroup`` for a single exception and then
extract the contained exception with the correct metadata.
incomplete and this could create problems.

Furthermore, as we explained in the `Handling ExceptionGroups`_ section, we
find it unlikely that iteration over leaf exceptions will have many use cases.
We did, however, provide there the code for a traversal algorithm that
correctly constructs each leaf exception's metadata. If it does turn out to
be useful in practice, we can add that utility to the standard library.

Traceback Representation
------------------------
Expand Down Expand Up @@ -1133,7 +1176,7 @@ See Also
========

* An analysis of how exception groups will likely be used in asyncio
programs: [11]_.
programs: [10]_.

* The issue where the ``except*`` concept was first formalized: [12]_.

Expand Down Expand Up @@ -1163,9 +1206,9 @@ References
.. [9] https://trio.readthedocs.io/en/stable/reference-core.html#trio.MultiError
.. [10] https://github.com/iritkatriel/cpython/tree/exceptionGroup-stage5
.. [10] https://github.com/python/exceptiongroups/issues/3#issuecomment-716203284
.. [11] https://github.com/python/exceptiongroups/issues/3#issuecomment-716203284
.. [11] https://github.com/iritkatriel/cpython/tree/exceptionGroup-stage5
.. [12] https://github.com/python/exceptiongroups/issues/4
Expand Down

0 comments on commit d729120

Please sign in to comment.