Skip to content

Commit 9b3447c

Browse files
[3.11] gh-101100: Improve docs on exception attributes (GH-113057) (#113062)
gh-101100: Improve docs on exception attributes (GH-113057) (cherry picked from commit d05a180) Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
1 parent 5fd915d commit 9b3447c

File tree

6 files changed

+115
-67
lines changed

6 files changed

+115
-67
lines changed

Doc/c-api/exceptions.rst

+10-6
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,8 @@ Querying the error indicator
456456
457457
.. note::
458458
459-
This function *does not* implicitly set the ``__traceback__``
459+
This function *does not* implicitly set the
460+
:attr:`~BaseException.__traceback__`
460461
attribute on the exception value. If setting the traceback
461462
appropriately is desired, the following additional snippet is needed::
462463
@@ -668,7 +669,8 @@ Exception Objects
668669
.. c:function:: PyObject* PyException_GetTraceback(PyObject *ex)
669670
670671
Return the traceback associated with the exception as a new reference, as
671-
accessible from Python through :attr:`__traceback__`. If there is no
672+
accessible from Python through the :attr:`~BaseException.__traceback__`
673+
attribute. If there is no
672674
traceback associated, this returns ``NULL``.
673675
674676
@@ -682,8 +684,8 @@ Exception Objects
682684
683685
Return the context (another exception instance during whose handling *ex* was
684686
raised) associated with the exception as a new reference, as accessible from
685-
Python through :attr:`__context__`. If there is no context associated, this
686-
returns ``NULL``.
687+
Python through the :attr:`~BaseException.__context__` attribute.
688+
If there is no context associated, this returns ``NULL``.
687689
688690
689691
.. c:function:: void PyException_SetContext(PyObject *ex, PyObject *ctx)
@@ -697,7 +699,8 @@ Exception Objects
697699
698700
Return the cause (either an exception instance, or ``None``,
699701
set by ``raise ... from ...``) associated with the exception as a new
700-
reference, as accessible from Python through :attr:`__cause__`.
702+
reference, as accessible from Python through the
703+
:attr:`~BaseException.__cause__` attribute.
701704
702705
703706
.. c:function:: void PyException_SetCause(PyObject *ex, PyObject *cause)
@@ -706,7 +709,8 @@ Exception Objects
706709
it. There is no type check to make sure that *cause* is either an exception
707710
instance or ``None``. This steals a reference to *cause*.
708711
709-
:attr:`__suppress_context__` is implicitly set to ``True`` by this function.
712+
The :attr:`~BaseException.__suppress_context__` attribute is implicitly set
713+
to ``True`` by this function.
710714
711715
712716
.. _unicodeexceptions:

Doc/library/exceptions.rst

+59-35
Original file line numberDiff line numberDiff line change
@@ -38,36 +38,48 @@ information on defining exceptions is available in the Python Tutorial under
3838
Exception context
3939
-----------------
4040

41-
When raising a new exception while another exception
42-
is already being handled, the new exception's
43-
:attr:`__context__` attribute is automatically set to the handled
44-
exception. An exception may be handled when an :keyword:`except` or
45-
:keyword:`finally` clause, or a :keyword:`with` statement, is used.
46-
47-
This implicit exception context can be
48-
supplemented with an explicit cause by using :keyword:`!from` with
49-
:keyword:`raise`::
50-
51-
raise new_exc from original_exc
52-
53-
The expression following :keyword:`from<raise>` must be an exception or ``None``. It
54-
will be set as :attr:`__cause__` on the raised exception. Setting
55-
:attr:`__cause__` also implicitly sets the :attr:`__suppress_context__`
56-
attribute to ``True``, so that using ``raise new_exc from None``
57-
effectively replaces the old exception with the new one for display
58-
purposes (e.g. converting :exc:`KeyError` to :exc:`AttributeError`), while
59-
leaving the old exception available in :attr:`__context__` for introspection
60-
when debugging.
61-
62-
The default traceback display code shows these chained exceptions in
63-
addition to the traceback for the exception itself. An explicitly chained
64-
exception in :attr:`__cause__` is always shown when present. An implicitly
65-
chained exception in :attr:`__context__` is shown only if :attr:`__cause__`
66-
is :const:`None` and :attr:`__suppress_context__` is false.
67-
68-
In either case, the exception itself is always shown after any chained
69-
exceptions so that the final line of the traceback always shows the last
70-
exception that was raised.
41+
.. index:: pair: exception; chaining
42+
__cause__ (exception attribute)
43+
__context__ (exception attribute)
44+
__suppress_context__ (exception attribute)
45+
46+
Three attributes on exception objects provide information about the context in
47+
which an the exception was raised:
48+
49+
.. attribute:: BaseException.__context__
50+
BaseException.__cause__
51+
BaseException.__suppress_context__
52+
53+
When raising a new exception while another exception
54+
is already being handled, the new exception's
55+
:attr:`!__context__` attribute is automatically set to the handled
56+
exception. An exception may be handled when an :keyword:`except` or
57+
:keyword:`finally` clause, or a :keyword:`with` statement, is used.
58+
59+
This implicit exception context can be
60+
supplemented with an explicit cause by using :keyword:`!from` with
61+
:keyword:`raise`::
62+
63+
raise new_exc from original_exc
64+
65+
The expression following :keyword:`from<raise>` must be an exception or ``None``. It
66+
will be set as :attr:`!__cause__` on the raised exception. Setting
67+
:attr:`!__cause__` also implicitly sets the :attr:`!__suppress_context__`
68+
attribute to ``True``, so that using ``raise new_exc from None``
69+
effectively replaces the old exception with the new one for display
70+
purposes (e.g. converting :exc:`KeyError` to :exc:`AttributeError`), while
71+
leaving the old exception available in :attr:`!__context__` for introspection
72+
when debugging.
73+
74+
The default traceback display code shows these chained exceptions in
75+
addition to the traceback for the exception itself. An explicitly chained
76+
exception in :attr:`!__cause__` is always shown when present. An implicitly
77+
chained exception in :attr:`!__context__` is shown only if :attr:`!__cause__`
78+
is :const:`None` and :attr:`!__suppress_context__` is false.
79+
80+
In either case, the exception itself is always shown after any chained
81+
exceptions so that the final line of the traceback always shows the last
82+
exception that was raised.
7183

7284

7385
Inheriting from built-in exceptions
@@ -126,6 +138,12 @@ The following exceptions are used mostly as base classes for other exceptions.
126138
tb = sys.exception().__traceback__
127139
raise OtherException(...).with_traceback(tb)
128140

141+
.. attribute:: __traceback__
142+
143+
A writable field that holds the
144+
:ref:`traceback object <traceback-objects>` associated with this
145+
exception. See also: :ref:`raise`.
146+
129147
.. method:: add_note(note)
130148

131149
Add the string ``note`` to the exception's notes which appear in the standard
@@ -928,8 +946,10 @@ their subgroups based on the types of the contained exceptions.
928946
same check that is used in an ``except`` clause.
929947

930948
The nesting structure of the current exception is preserved in the result,
931-
as are the values of its :attr:`message`, :attr:`__traceback__`,
932-
:attr:`__cause__`, :attr:`__context__` and :attr:`__notes__` fields.
949+
as are the values of its :attr:`message`,
950+
:attr:`~BaseException.__traceback__`, :attr:`~BaseException.__cause__`,
951+
:attr:`~BaseException.__context__` and
952+
:attr:`~BaseException.__notes__` fields.
933953
Empty nested groups are omitted from the result.
934954

935955
The condition is checked for all exceptions in the nested exception group,
@@ -952,10 +972,14 @@ their subgroups based on the types of the contained exceptions.
952972
and :meth:`split` return instances of the subclass rather
953973
than :exc:`ExceptionGroup`.
954974

955-
:meth:`subgroup` and :meth:`split` copy the :attr:`__traceback__`,
956-
:attr:`__cause__`, :attr:`__context__` and :attr:`__notes__` fields from
975+
:meth:`subgroup` and :meth:`split` copy the
976+
:attr:`~BaseException.__traceback__`,
977+
:attr:`~BaseException.__cause__`, :attr:`~BaseException.__context__` and
978+
:attr:`~BaseException.__notes__` fields from
957979
the original exception group to the one returned by :meth:`derive`, so
958-
these fields do not need to be updated by :meth:`derive`. ::
980+
these fields do not need to be updated by :meth:`derive`.
981+
982+
.. doctest::
959983

960984
>>> class MyGroup(ExceptionGroup):
961985
... def derive(self, excs):

Doc/library/traceback.rst

+18-12
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ The module defines the following functions:
6767

6868
The optional *limit* argument has the same meaning as for :func:`print_tb`.
6969
If *chain* is true (the default), then chained exceptions (the
70-
:attr:`__cause__` or :attr:`__context__` attributes of the exception) will be
70+
:attr:`~BaseException.__cause__` or :attr:`~BaseException.__context__`
71+
attributes of the exception) will be
7172
printed as well, like the interpreter itself does when printing an unhandled
7273
exception.
7374

@@ -228,10 +229,11 @@ capture data for later printing in a lightweight fashion.
228229
Capture an exception for later rendering. *limit*, *lookup_lines* and
229230
*capture_locals* are as for the :class:`StackSummary` class.
230231

231-
If *compact* is true, only data that is required by :class:`TracebackException`'s
232-
``format`` method is saved in the class attributes. In particular, the
233-
``__context__`` field is calculated only if ``__cause__`` is ``None`` and
234-
``__suppress_context__`` is false.
232+
If *compact* is true, only data that is required by
233+
:class:`!TracebackException`'s :meth:`format` method
234+
is saved in the class attributes. In particular, the
235+
:attr:`__context__` field is calculated only if :attr:`__cause__` is
236+
``None`` and :attr:`__suppress_context__` is false.
235237

236238
Note that when locals are captured, they are also shown in the traceback.
237239

@@ -249,27 +251,31 @@ capture data for later printing in a lightweight fashion.
249251

250252
.. attribute:: __cause__
251253

252-
A :class:`TracebackException` of the original ``__cause__``.
254+
A :class:`!TracebackException` of the original
255+
:attr:`~BaseException.__cause__`.
253256

254257
.. attribute:: __context__
255258

256-
A :class:`TracebackException` of the original ``__context__``.
259+
A :class:`!TracebackException` of the original
260+
:attr:`~BaseException.__context__`.
257261

258262
.. attribute:: exceptions
259263

260264
If ``self`` represents an :exc:`ExceptionGroup`, this field holds a list of
261-
:class:`TracebackException` instances representing the nested exceptions.
265+
:class:`!TracebackException` instances representing the nested exceptions.
262266
Otherwise it is ``None``.
263267

264268
.. versionadded:: 3.11
265269

266270
.. attribute:: __suppress_context__
267271

268-
The ``__suppress_context__`` value from the original exception.
272+
The :attr:`~BaseException.__suppress_context__` value from the original
273+
exception.
269274

270275
.. attribute:: __notes__
271276

272-
The ``__notes__`` value from the original exception, or ``None``
277+
The :attr:`~BaseException.__notes__` value from the original exception,
278+
or ``None``
273279
if the exception does not have any notes. If it is not ``None``
274280
is it formatted in the traceback after the exception string.
275281

@@ -335,8 +341,8 @@ capture data for later printing in a lightweight fashion.
335341

336342
Format the exception.
337343

338-
If *chain* is not ``True``, ``__cause__`` and ``__context__`` will not
339-
be formatted.
344+
If *chain* is not ``True``, :attr:`__cause__` and :attr:`__context__`
345+
will not be formatted.
340346

341347
The return value is a generator of strings, each ending in a newline and
342348
some containing internal newlines. :func:`~traceback.print_exception`

Doc/reference/datamodel.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -1368,7 +1368,8 @@ unwinds the execution stack, at each unwound level a traceback object is
13681368
inserted in front of the current traceback. When an exception handler is
13691369
entered, the stack trace is made available to the program. (See section
13701370
:ref:`try`.) It is accessible as the third item of the
1371-
tuple returned by :func:`sys.exc_info`, and as the ``__traceback__`` attribute
1371+
tuple returned by :func:`sys.exc_info`, and as the
1372+
:attr:`~BaseException.__traceback__` attribute
13721373
of the caught exception.
13731374

13741375
When the program contains no suitable

Doc/reference/simple_stmts.rst

+20-8
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ The :dfn:`type` of the exception is the exception instance's class, the
577577
.. index:: pair: object; traceback
578578

579579
A traceback object is normally created automatically when an exception is raised
580-
and attached to it as the :attr:`__traceback__` attribute, which is writable.
580+
and attached to it as the :attr:`~BaseException.__traceback__` attribute.
581581
You can create an exception and set your own traceback in one step using the
582582
:meth:`~BaseException.with_traceback` exception method (which returns the
583583
same exception instance, with its traceback set to its argument), like so::
@@ -591,11 +591,13 @@ same exception instance, with its traceback set to its argument), like so::
591591
The ``from`` clause is used for exception chaining: if given, the second
592592
*expression* must be another exception class or instance. If the second
593593
expression is an exception instance, it will be attached to the raised
594-
exception as the :attr:`__cause__` attribute (which is writable). If the
594+
exception as the :attr:`~BaseException.__cause__` attribute (which is writable). If the
595595
expression is an exception class, the class will be instantiated and the
596596
resulting exception instance will be attached to the raised exception as the
597-
:attr:`__cause__` attribute. If the raised exception is not handled, both
598-
exceptions will be printed::
597+
:attr:`!__cause__` attribute. If the raised exception is not handled, both
598+
exceptions will be printed:
599+
600+
.. code-block:: pycon
599601
600602
>>> try:
601603
... print(1 / 0)
@@ -604,19 +606,24 @@ exceptions will be printed::
604606
...
605607
Traceback (most recent call last):
606608
File "<stdin>", line 2, in <module>
609+
print(1 / 0)
610+
~~^~~
607611
ZeroDivisionError: division by zero
608612
609613
The above exception was the direct cause of the following exception:
610614
611615
Traceback (most recent call last):
612616
File "<stdin>", line 4, in <module>
617+
raise RuntimeError("Something bad happened") from exc
613618
RuntimeError: Something bad happened
614619
615620
A similar mechanism works implicitly if a new exception is raised when
616621
an exception is already being handled. An exception may be handled
617622
when an :keyword:`except` or :keyword:`finally` clause, or a
618623
:keyword:`with` statement, is used. The previous exception is then
619-
attached as the new exception's :attr:`__context__` attribute::
624+
attached as the new exception's :attr:`~BaseException.__context__` attribute:
625+
626+
.. code-block:: pycon
620627
621628
>>> try:
622629
... print(1 / 0)
@@ -625,16 +632,21 @@ attached as the new exception's :attr:`__context__` attribute::
625632
...
626633
Traceback (most recent call last):
627634
File "<stdin>", line 2, in <module>
635+
print(1 / 0)
636+
~~^~~
628637
ZeroDivisionError: division by zero
629638
630639
During handling of the above exception, another exception occurred:
631640
632641
Traceback (most recent call last):
633642
File "<stdin>", line 4, in <module>
643+
raise RuntimeError("Something bad happened")
634644
RuntimeError: Something bad happened
635645
636646
Exception chaining can be explicitly suppressed by specifying :const:`None` in
637-
the ``from`` clause::
647+
the ``from`` clause:
648+
649+
.. doctest::
638650

639651
>>> try:
640652
... print(1 / 0)
@@ -652,8 +664,8 @@ and information about handling exceptions is in section :ref:`try`.
652664
:const:`None` is now permitted as ``Y`` in ``raise X from Y``.
653665

654666
.. versionadded:: 3.3
655-
The ``__suppress_context__`` attribute to suppress automatic display of the
656-
exception context.
667+
The :attr:`~BaseException.__suppress_context__` attribute to suppress
668+
automatic display of the exception context.
657669

658670
.. versionchanged:: 3.11
659671
If the traceback of the active exception is modified in an :keyword:`except`

Doc/whatsnew/3.0.rst

+6-5
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ new powerful features added:
711711
{Exception}({args})` instead of :samp:`raise {Exception}, {args}`.
712712
Additionally, you can no longer explicitly specify a traceback;
713713
instead, if you *have* to do this, you can assign directly to the
714-
:attr:`__traceback__` attribute (see below).
714+
:attr:`~BaseException.__traceback__` attribute (see below).
715715

716716
* :pep:`3110`: Catching exceptions. You must now use
717717
:samp:`except {SomeException} as {variable}` instead
@@ -725,22 +725,23 @@ new powerful features added:
725725
handler block. This usually happens due to a bug in the handler
726726
block; we call this a *secondary* exception. In this case, the
727727
original exception (that was being handled) is saved as the
728-
:attr:`__context__` attribute of the secondary exception.
728+
:attr:`~BaseException.__context__` attribute of the secondary exception.
729729
Explicit chaining is invoked with this syntax::
730730

731731
raise SecondaryException() from primary_exception
732732

733733
(where *primary_exception* is any expression that produces an
734734
exception object, probably an exception that was previously caught).
735735
In this case, the primary exception is stored on the
736-
:attr:`__cause__` attribute of the secondary exception. The
736+
:attr:`~BaseException.__cause__` attribute of the secondary exception. The
737737
traceback printed when an unhandled exception occurs walks the chain
738-
of :attr:`__cause__` and :attr:`__context__` attributes and prints a
738+
of :attr:`!__cause__` and :attr:`~BaseException.__context__` attributes and
739+
prints a
739740
separate traceback for each component of the chain, with the primary
740741
exception at the top. (Java users may recognize this behavior.)
741742

742743
* :pep:`3134`: Exception objects now store their traceback as the
743-
:attr:`__traceback__` attribute. This means that an exception
744+
:attr:`~BaseException.__traceback__` attribute. This means that an exception
744745
object now contains all the information pertaining to an exception,
745746
and there are fewer reasons to use :func:`sys.exc_info` (though the
746747
latter is not removed).

0 commit comments

Comments
 (0)