From 31ba5bd70c2d563013a4ee4e789e47ea3de2d5d8 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sat, 27 Feb 2021 00:59:40 +0000 Subject: [PATCH] PEP 654: Explain why we did not extend except to handle ExceptionGroups (#1846) --- pep-0654.rst | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/pep-0654.rst b/pep-0654.rst index 7cc217d8f..8912e3dac 100644 --- a/pep-0654.rst +++ b/pep-0654.rst @@ -108,6 +108,10 @@ other types in the same ``ExceptionGroup`` need to be automatically reraised, otherwise it is too easy for user code to inadvertently swallow exceptions that it is not handling. +We considered whether it is possible to modify the semantics of ``except`` +for this purpose, in a backwards-compatible manner, and found that it is not. +See the `Rejected Ideas`_ section for more on this. + The purpose of this PEP, then, is to add the ``except*`` syntax for handling ``ExceptionGroups`` in the interpreter, which in turn requires that ``ExceptionGroup`` is added as a builtin type. The semantics of handling @@ -1017,8 +1021,33 @@ group. Furthermore, a useful display of the traceback includes information about the nested exceptions. For these reasons we decided that it is best to leave the traceback mechanism as it is and modify the traceback display code. -A full redesign of ``except`` ------------------------------ +Extend ``except`` to handle ``ExceptionGroups`` +----------------------------------------------- + +We considered extending the semantics of ``except`` to handle +``ExceptionGroups``, instead of introducing ``except*``. There were two +backwards compatibility concerns with this. The first is the type of the +caught exception. Consider this example: + +.. code-block:: + + try: + . . . + except OSError as err: + if err.errno != ENOENT: + raise + +If the value assigned to err is an ``ExceptionGroup`` containing all of +the ``OSErrors`` that were raised, then the attribute access ``err.errno`` +no longer works. So we would need to execute the body of the ``except`` +clause multiple times, once for each exception in the group. However, this +too is a potentially breaking change because at the moment we write ``except`` +clauses with the knowledge that they are only executed once. If there is +a non-idempotent operation there, such as releasing a resource, the +repetition could be harmful. + +A new ``except`` alternative +---------------------------- We considered introducing a new keyword (such as ``catch``) which can be used to handle both naked exceptions and ``ExceptionGroups``. Its semantics would @@ -1033,7 +1062,10 @@ continues to be used for simple exceptions. Applying an ``except*`` clause on one exception at a time --------------------------------------------------------- -We considered making ``except*`` clauses always execute on a single exception, +We explained above why it is unsafe to execute an ``except`` clause in existing +code more than once. We considered doing this in the new ``except*`` clauses, +where the backwards compatibility considerations do not exist. +The idea is to always execute an ``except*`` clause on a single exception, possibly executing the same clause multiple times when it matches multiple exceptions. We decided instead to execute each ``except*`` clause at most once, giving it an ``ExceptionGroup`` that contains all matching exceptions. The