mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-135629: rewrite language reference section on except* to improve clarity (#136150)
This commit is contained in:
parent
01cc53295c
commit
a651ec9524
1 changed files with 32 additions and 28 deletions
|
|
@ -335,15 +335,29 @@ stored in the :mod:`sys` module is reset to its previous value::
|
||||||
:keyword:`!except*` clause
|
:keyword:`!except*` clause
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
The :keyword:`!except*` clause(s) are used for handling
|
The :keyword:`!except*` clause(s) specify one or more handlers for groups of
|
||||||
:exc:`ExceptionGroup`\s. The exception type for matching is interpreted as in
|
exceptions (:exc:`BaseExceptionGroup` instances). A :keyword:`try` statement
|
||||||
the case of :keyword:`except`, but in the case of exception groups we can have
|
can have either :keyword:`except` or :keyword:`!except*` clauses, but not both.
|
||||||
partial matches when the type matches some of the exceptions in the group.
|
The exception type for matching is mandatory in the case of :keyword:`!except*`,
|
||||||
This means that multiple :keyword:`!except*` clauses can execute,
|
so ``except*:`` is a syntax error. The type is interpreted as in the case of
|
||||||
each handling part of the exception group.
|
:keyword:`!except`, but matching is performed on the exceptions contained in the
|
||||||
Each clause executes at most once and handles an exception group
|
group that is being handled. An :exc:`TypeError` is raised if a matching
|
||||||
of all matching exceptions. Each exception in the group is handled by at most
|
type is a subclass of :exc:`!BaseExceptionGroup`, because that would have
|
||||||
one :keyword:`!except*` clause, the first that matches it. ::
|
ambiguous semantics.
|
||||||
|
|
||||||
|
When an exception group is raised in the try block, each :keyword:`!except*`
|
||||||
|
clause splits (see :meth:`~BaseExceptionGroup.split`) it into the subgroups
|
||||||
|
of matching and non-matching exceptions. If the matching subgroup is not empty,
|
||||||
|
it becomes the handled exception (the value returned from :func:`sys.exception`)
|
||||||
|
and assigned to the target of the :keyword:`!except*` clause (if there is one).
|
||||||
|
Then, the body of the :keyword:`!except*` clause executes. If the non-matching
|
||||||
|
subgroup is not empty, it is processed by the next :keyword:`!except*` in the
|
||||||
|
same manner. This continues until all exceptions in the group have been matched,
|
||||||
|
or the last :keyword:`!except*` clause has run.
|
||||||
|
|
||||||
|
After all :keyword:`!except*` clauses execute, the group of unhandled exceptions
|
||||||
|
is merged with any exceptions that were raised or re-raised from within
|
||||||
|
:keyword:`!except*` clauses. This merged exception group propagates on.::
|
||||||
|
|
||||||
>>> try:
|
>>> try:
|
||||||
... raise ExceptionGroup("eg",
|
... raise ExceptionGroup("eg",
|
||||||
|
|
@ -356,22 +370,18 @@ one :keyword:`!except*` clause, the first that matches it. ::
|
||||||
caught <class 'ExceptionGroup'> with nested (TypeError(2),)
|
caught <class 'ExceptionGroup'> with nested (TypeError(2),)
|
||||||
caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
|
caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
|
||||||
+ Exception Group Traceback (most recent call last):
|
+ Exception Group Traceback (most recent call last):
|
||||||
| File "<stdin>", line 2, in <module>
|
| File "<doctest default[0]>", line 2, in <module>
|
||||||
| ExceptionGroup: eg
|
| raise ExceptionGroup("eg",
|
||||||
|
| [ValueError(1), TypeError(2), OSError(3), OSError(4)])
|
||||||
|
| ExceptionGroup: eg (1 sub-exception)
|
||||||
+-+---------------- 1 ----------------
|
+-+---------------- 1 ----------------
|
||||||
| ValueError: 1
|
| ValueError: 1
|
||||||
+------------------------------------
|
+------------------------------------
|
||||||
|
|
||||||
|
If the exception raised from the :keyword:`try` block is not an exception group
|
||||||
Any remaining exceptions that were not handled by any :keyword:`!except*`
|
and its type matches one of the :keyword:`!except*` clauses, it is caught and
|
||||||
clause are re-raised at the end, along with all exceptions that were
|
wrapped by an exception group with an empty message string. This ensures that the
|
||||||
raised from within the :keyword:`!except*` clauses. If this list contains
|
type of the target ``e`` is consistently :exc:`BaseExceptionGroup`::
|
||||||
more than one exception to reraise, they are combined into an exception
|
|
||||||
group.
|
|
||||||
|
|
||||||
If the raised exception is not an exception group and its type matches
|
|
||||||
one of the :keyword:`!except*` clauses, it is caught and wrapped by an
|
|
||||||
exception group with an empty message string. ::
|
|
||||||
|
|
||||||
>>> try:
|
>>> try:
|
||||||
... raise BlockingIOError
|
... raise BlockingIOError
|
||||||
|
|
@ -380,13 +390,7 @@ exception group with an empty message string. ::
|
||||||
...
|
...
|
||||||
ExceptionGroup('', (BlockingIOError()))
|
ExceptionGroup('', (BlockingIOError()))
|
||||||
|
|
||||||
An :keyword:`!except*` clause must have a matching expression; it cannot be ``except*:``.
|
:keyword:`break`, :keyword:`continue` and :keyword:`return`
|
||||||
Furthermore, this expression cannot contain exception group types, because that would
|
|
||||||
have ambiguous semantics.
|
|
||||||
|
|
||||||
It is not possible to mix :keyword:`except` and :keyword:`!except*`
|
|
||||||
in the same :keyword:`try`.
|
|
||||||
The :keyword:`break`, :keyword:`continue`, and :keyword:`return` statements
|
|
||||||
cannot appear in an :keyword:`!except*` clause.
|
cannot appear in an :keyword:`!except*` clause.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue