summaryrefslogtreecommitdiffstats
path: root/Doc/tutorial
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2022-01-06 19:05:34 (GMT)
committerGitHub <noreply@github.com>2022-01-06 19:05:34 (GMT)
commit9925e70e4811841556747a77acd89c1a70bf344a (patch)
tree8be9c36aebbe390ab92e8db0f2ad477e5a09eec7 /Doc/tutorial
parent68c76d9766cccb5fd992b0ac4b39645d9665dbe2 (diff)
downloadcpython-9925e70e4811841556747a77acd89c1a70bf344a.zip
cpython-9925e70e4811841556747a77acd89c1a70bf344a.tar.gz
cpython-9925e70e4811841556747a77acd89c1a70bf344a.tar.bz2
bpo-45292: [PEP-654] exception groups and except* documentation (GH-30158)
Diffstat (limited to 'Doc/tutorial')
-rw-r--r--Doc/tutorial/errors.rst89
1 files changed, 89 insertions, 0 deletions
diff --git a/Doc/tutorial/errors.rst b/Doc/tutorial/errors.rst
index 3f09db2..ad1ef84 100644
--- a/Doc/tutorial/errors.rst
+++ b/Doc/tutorial/errors.rst
@@ -462,3 +462,92 @@ used in a way that ensures they are always cleaned up promptly and correctly. ::
After the statement is executed, the file *f* is always closed, even if a
problem was encountered while processing the lines. Objects which, like files,
provide predefined clean-up actions will indicate this in their documentation.
+
+
+.. _tut-exception-groups:
+
+Raising and Handling Multiple Unrelated Exceptions
+==================================================
+
+There are situations where it is necessary to report several exceptions that
+have occurred. This it often the case in concurrency frameworks, when several
+tasks may have failed in parallel, but there are also other use cases where
+it is desirable to continue execution and collect multiple errors rather than
+raise the first exception.
+
+The builtin :exc:`ExceptionGroup` wraps a list of exception instances so
+that they can be raised together. It is an exception itself, so it can be
+caught like any other exception. ::
+
+ >>> def f():
+ ... excs = [OSError('error 1'), SystemError('error 2')]
+ ... raise ExceptionGroup('there were problems', excs)
+ ...
+ >>> f()
+ + Exception Group Traceback (most recent call last):
+ | File "<stdin>", line 1, in <module>
+ | File "<stdin>", line 3, in f
+ | ExceptionGroup: there were problems
+ +-+---------------- 1 ----------------
+ | OSError: error 1
+ +---------------- 2 ----------------
+ | SystemError: error 2
+ +------------------------------------
+ >>> try:
+ ... f()
+ ... except Exception as e:
+ ... print(f'caught {type(e)}: e')
+ ...
+ caught <class 'ExceptionGroup'>: e
+ >>>
+
+By using ``except*`` instead of ``except``, we can selectively
+handle only the exceptions in the group that match a certain
+type. In the following example, which shows a nested exception
+group, each ``except*`` clause extracts from the group exceptions
+of a certain type while letting all other exceptions propagate to
+other clauses and eventually to be reraised. ::
+
+ >>> def f():
+ ... raise ExceptionGroup("group1",
+ ... [OSError(1),
+ ... SystemError(2),
+ ... ExceptionGroup("group2",
+ ... [OSError(3), RecursionError(4)])])
+ ...
+ >>> try:
+ ... f()
+ ... except* OSError as e:
+ ... print("There were OSErrors")
+ ... except* SystemError as e:
+ ... print("There were SystemErrors")
+ ...
+ There were OSErrors
+ There were SystemErrors
+ + Exception Group Traceback (most recent call last):
+ | File "<stdin>", line 2, in <module>
+ | File "<stdin>", line 2, in f
+ | ExceptionGroup: group1
+ +-+---------------- 1 ----------------
+ | ExceptionGroup: group2
+ +-+---------------- 1 ----------------
+ | RecursionError: 4
+ +------------------------------------
+ >>>
+
+Note that the exceptions nested in an exception group must be instances,
+not types. This is because in practice the exceptions would typically
+be ones that have already been raised and caught by the program, along
+the following pattern::
+
+ >>> excs = []
+ ... for test in tests:
+ ... try:
+ ... test.run()
+ ... except Exception as e:
+ ... excs.append(e)
+ ...
+ >>> if excs:
+ ... raise ExceptionGroup("Test Failures", excs)
+ ...
+