https://github.com/python/cpython/commit/80f9604d1189e382fe2274ce78998b347afd2627
commit: 80f9604d1189e382fe2274ce78998b347afd2627
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: encukou <[email protected]>
date: 2026-09-03T12:41:28+02:00
summary:

[3.14] Reword `atexit` docs (GH-156086) (GH-156879)

For the `atexit` module:

- Move common info from `register` to the module level (a lot of this
  was duplicated -- less maintainable and harder to read)
- Use *interpreter shutdown* consistently, introducing it as a more
  general term for the old docs' *program termination*.
- Use the term *exit handler* consistently
- Move warning for a mitigated footgun to a change entry
- Add a new warning about keeping things usable

Similarly clarify docs for the `atexit` attribute in `weakref`.
(cherry picked from commit 1d28836e43efba08ac71d91d135d721e1f4ada69)

Co-authored-by: Petr Viktorin <[email protected]>

files:
M Doc/library/atexit.rst
M Doc/library/weakref.rst

diff --git a/Doc/library/atexit.rst b/Doc/library/atexit.rst
index 24a3492ba10c91..10c4ca2ca5aff2 100644
--- a/Doc/library/atexit.rst
+++ b/Doc/library/atexit.rst
@@ -9,59 +9,69 @@
 
 --------------
 
-The :mod:`!atexit` module defines functions to register and unregister cleanup
-functions.  Functions thus registered are automatically executed upon normal
-interpreter termination.  :mod:`!atexit` runs these functions in the *reverse*
-order in which they were registered; if you register ``A``, ``B``, and ``C``,
-at interpreter termination time they will be run in the order ``C``, ``B``,
-``A``.
-
-**Note:** The functions registered via this module are not called when the
+The :mod:`!atexit` module defines functions to register and unregister
+:dfn:`exit handlers`: functions that are automatically executed
+"at exit", that is, upon normal program termination (for instance,
+if :func:`sys.exit` is called or the main module's execution completes)
+or, more generally, upon :term:`interpreter shutdown`.
+
+At exit, all registered exit handlers are called
+in the *reverse* order in which they were registered.
+If you register ``A``, ``B``, and ``C``, at interpreter shutdown time they
+will be run in the order ``C``, ``B``, ``A``.
+The assumption is that lower level modules will normally be imported before
+higher level modules and thus must be cleaned up later.
+
+If an exception is raised during execution of an exit handler, a traceback is
+printed (unless :exc:`SystemExit` is raised) and the exception information is
+saved.  After all exit handlers have had a chance to run, the last exception to
+be raised is re-raised.
+
+In programs that use multiple interpreters, each interpreter has its own stack
+of exit handlers, which are executed when the interpreter shuts down
+(for example, with :meth:`concurrent.interpreters.Interpreter.close` or the
+C API :c:func:`Py_EndInterpreter`).
+Registration functions in this module only affect the interpreter they are
+called from.
+
+**Note:** Exit handlers are not called when the
 program is killed by a signal not handled by Python, when a Python fatal
 internal error is detected, or when :func:`os._exit` is called.
 
 **Note:** The effect of registering or unregistering functions from within
 a cleanup function is undefined.
 
-.. versionchanged:: 3.7
-    When used with C-API subinterpreters, registered functions
-    are local to the interpreter they were registered in.
+.. warning::
+   When writing exit handlers, especially in C API extensions, keep in mind
+   that other exit handlers may still run arbitrary Python code after you
+   clean up.
+   Such code should succeed or fail with an exception, rather than crash.
 
-.. function:: register(func, *args, **kwargs)
+.. versionchanged:: 3.12
+   Attempts to start a new thread or :func:`os.fork` a new process
+   in an exit handler now leads to :exc:`RuntimeError`.
+   Previously, this could cause race conditions between the main Python
+   runtime thread freeing thread states while internal :mod:`threading`
+   routines or the new process try to use that state, which could lead to
+   crashes rather than clean shutdown.
 
-   Register *func* as a function to be executed at termination.  Any optional
-   arguments that are to be passed to *func* must be passed as arguments to
-   :func:`register`.  It is possible to register the same function and 
arguments
-   more than once.
+.. versionchanged:: 3.7
+   When used with subinterpreters, registered functions
+   are local to the interpreter they were registered in.
 
-   At normal program termination (for instance, if :func:`sys.exit` is called 
or
-   the main module's execution completes), all functions registered are called 
in
-   last in, first out order.  The assumption is that lower level modules will
-   normally be imported before higher level modules and thus must be cleaned up
-   later.
+.. function:: register(func, *args, **kwargs)
 
-   If an exception is raised during execution of the exit handlers, a 
traceback is
-   printed (unless :exc:`SystemExit` is raised) and the exception information 
is
-   saved.  After all exit handlers have had a chance to run, the last 
exception to
-   be raised is re-raised.
+   Register *func* as an exit handler.
+   Any optional arguments that are to be passed to *func* must be passed as
+   arguments to :func:`register`.
+   It is possible to register the same function and arguments more than once.
 
    This function returns *func*, which makes it possible to use it as a
    decorator.
 
-   .. warning::
-       Starting new threads or calling :func:`os.fork` from a registered
-       function can lead to race condition between the main Python
-       runtime thread freeing thread states while internal :mod:`threading`
-       routines or the new process try to use that state. This can lead to
-       crashes rather than clean shutdown.
-
-   .. versionchanged:: 3.12
-       Attempts to start a new thread or :func:`os.fork` a new process
-       in a registered function now leads to :exc:`RuntimeError`.
-
 .. function:: unregister(func)
 
-   Remove *func* from the list of functions to be run at interpreter shutdown.
+   Remove *func* from the list of exit handlers.
    :func:`unregister` silently does nothing if *func* was not previously
    registered.  If *func* has been registered more than once, every occurrence
    of that function in the :mod:`!atexit` call stack will be removed.  Equality
diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst
index a05a46fd215d03..38d9405cde0cc7 100644
--- a/Doc/library/weakref.rst
+++ b/Doc/library/weakref.rst
@@ -286,9 +286,10 @@ same issues as the :meth:`WeakKeyDictionary.keyrefs` 
method.
    from an object's :meth:`~object.__del__` method or a weak reference's
    callback.
 
-   When the program exits, each remaining live finalizer is called
-   unless its :attr:`atexit` attribute has been set to false.  They
-   are called in reverse order of creation.
+   When the program exits (or more generally, at :term:`interpreter shutdown`),
+   each remaining live finalizer is called unless its :attr:`atexit` attribute
+   has been set to false.
+   They are called in reverse order of creation.
 
    A finalizer will never invoke its callback during the later part of
    the :term:`interpreter shutdown` when module globals are liable to have
@@ -317,9 +318,9 @@ same issues as the :meth:`WeakKeyDictionary.keyrefs` method.
 
    .. attribute:: atexit
 
-      A writable boolean property which by default is true.  When the
-      program exits, it calls all remaining live finalizers for which
-      :attr:`.atexit` is true.  They are called in reverse order of
+      A writable boolean property which by default is true.  At
+      :term:`interpreter shutdown`, all remaining live finalizers for which
+      :attr:`.atexit` is true are called in reverse order of
       creation.
 
    .. note::

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to