@@ -332,15 +332,29 @@ stored in the :mod:`sys` module is reset to its previous value::
332332:keyword: `!except* ` clause
333333--------------------------
334334
335- The :keyword: `!except* ` clause(s) are used for handling
336- :exc: `ExceptionGroup `\s . The exception type for matching is interpreted as in
337- the case of :keyword: `except `, but in the case of exception groups we can have
338- partial matches when the type matches some of the exceptions in the group.
339- This means that multiple :keyword: `!except* ` clauses can execute,
340- each handling part of the exception group.
341- Each clause executes at most once and handles an exception group
342- of all matching exceptions. Each exception in the group is handled by at most
343- one :keyword: `!except* ` clause, the first that matches it. ::
335+ The :keyword: `!except* ` clause(s) specify one or more handlers for groups of
336+ exceptions (:exc: `BaseExceptionGroup ` instances). A :keyword: `try ` statement
337+ can have either :keyword: `except ` or :keyword: `!except* ` clauses, but not both.
338+ The exception type for matching is mandatory in the case of :keyword: `!except* `,
339+ so ``except*: `` is a syntax error. The type is interpreted as in the case of
340+ :keyword: `!except `, but matching is performed on the exceptions contained in the
341+ group that is being handled. An :exc: `TypeError ` is raised if a matching
342+ type is a subclass of :exc: `!BaseExceptionGroup `, because that would have
343+ ambiguous semantics.
344+
345+ When an exception group is raised in the try block, each :keyword: `!except* `
346+ clause splits (see :meth: `~BaseExceptionGroup.split `) it into the subgroups
347+ of matching and non-matching exceptions. If the matching subgroup is not empty,
348+ it becomes the handled exception (the value returned from :func: `sys.exception `)
349+ and assigned to the target of the :keyword: `!except* ` clause (if there is one).
350+ Then, the body of the :keyword: `!except* ` clause executes. If the non-matching
351+ subgroup is not empty, it is processed by the next :keyword: `!except* ` in the
352+ same manner. This continues until all exceptions in the group have been matched,
353+ or the last :keyword: `!except* ` clause has run.
354+
355+ After all :keyword: `!except* ` clauses execute, the group of unhandled exceptions
356+ is merged with any exceptions that were raised or re-raised from within
357+ :keyword: `!except* ` clauses. This merged exception group propagates on.::
344358
345359 >>> try:
346360 ... raise ExceptionGroup("eg",
@@ -353,22 +367,18 @@ one :keyword:`!except*` clause, the first that matches it. ::
353367 caught <class 'ExceptionGroup'> with nested (TypeError(2),)
354368 caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
355369 + Exception Group Traceback (most recent call last):
356- | File "<stdin>", line 2, in <module>
357- | ExceptionGroup: eg
370+ | File "<doctest default[0]>", line 2, in <module>
371+ | raise ExceptionGroup("eg",
372+ | [ValueError(1), TypeError(2), OSError(3), OSError(4)])
373+ | ExceptionGroup: eg (1 sub-exception)
358374 +-+---------------- 1 ----------------
359375 | ValueError: 1
360376 +------------------------------------
361377
362-
363- Any remaining exceptions that were not handled by any :keyword: `!except* `
364- clause are re-raised at the end, along with all exceptions that were
365- raised from within the :keyword: `!except* ` clauses. If this list contains
366- more than one exception to reraise, they are combined into an exception
367- group.
368-
369- If the raised exception is not an exception group and its type matches
370- one of the :keyword: `!except* ` clauses, it is caught and wrapped by an
371- exception group with an empty message string. ::
378+ If the exception raised from the :keyword: `try ` block is not an exception group
379+ and its type matches one of the :keyword: `!except* ` clauses, it is caught and
380+ wrapped by an exception group with an empty message string. This ensures that the
381+ type of the target ``e `` is consistently :exc: `BaseExceptionGroup `::
372382
373383 >>> try:
374384 ... raise BlockingIOError
@@ -377,13 +387,7 @@ exception group with an empty message string. ::
377387 ...
378388 ExceptionGroup('', (BlockingIOError()))
379389
380- An :keyword: `!except* ` clause must have a matching expression; it cannot be ``except*: ``.
381- Furthermore, this expression cannot contain exception group types, because that would
382- have ambiguous semantics.
383-
384- It is not possible to mix :keyword: `except ` and :keyword: `!except* `
385- in the same :keyword: `try `.
386- The :keyword: `break `, :keyword: `continue `, and :keyword: `return ` statements
390+ :keyword: `break `, :keyword: `continue ` and :keyword: `return `
387391cannot appear in an :keyword: `!except* ` clause.
388392
389393
0 commit comments