summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doc/glossary.rst13
-rw-r--r--Doc/library/gc.rst6
-rw-r--r--Doc/library/sys.rst8
-rw-r--r--Doc/library/weakref.rst6
-rw-r--r--Lib/test/test_sys.py21
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/sysmodule.c11
7 files changed, 62 insertions, 6 deletions
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index 92877bd896..87e2d8a672 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -402,6 +402,19 @@ Glossary
than compiled ones, though their programs generally also run more
slowly. See also :term:`interactive`.
+ interpreter shutdown
+ When asked to shut down, the Python interpreter enters a special phase
+ where it gradually releases all allocated resources, such as modules
+ and various critical internal structures. It also makes several calls
+ to the :term:`garbage collector <garbage collection>`. This can trigger
+ the execution of code in user-defined destructors or weakref callbacks.
+ Code executed during the shutdown phase can encounter various
+ exceptions as the resources it relies on may not function anymore
+ (common examples are library modules or the warnings machinery).
+
+ The main reason for interpreter shutdown is that the ``__main__`` module
+ or the script being run has finished executing.
+
iterable
An object capable of returning its members one at a time. Examples of
iterables include all sequence types (such as :class:`list`, :class:`str`,
diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst
index 813554206a..d11c2e1282 100644
--- a/Doc/library/gc.rst
+++ b/Doc/library/gc.rst
@@ -186,7 +186,7 @@ values but should not rebind them):
added to this list rather than freed.
.. versionchanged:: 3.2
- If this list is non-empty at interpreter shutdown, a
+ If this list is non-empty at :term:`interpreter shutdown`, a
:exc:`ResourceWarning` is emitted, which is silent by default. If
:const:`DEBUG_UNCOLLECTABLE` is set, in addition all uncollectable objects
are printed.
@@ -252,8 +252,8 @@ The following constants are provided for use with :func:`set_debug`:
to the ``garbage`` list.
.. versionchanged:: 3.2
- Also print the contents of the :data:`garbage` list at interpreter
- shutdown, if it isn't empty.
+ Also print the contents of the :data:`garbage` list at
+ :term:`interpreter shutdown`, if it isn't empty.
.. data:: DEBUG_SAVEALL
diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst
index 3024086a22..fa125a0c96 100644
--- a/Doc/library/sys.rst
+++ b/Doc/library/sys.rst
@@ -718,6 +718,14 @@ always available.
value of :func:`intern` around to benefit from it.
+.. function:: is_finalizing()
+
+ Return :const:`True` if the Python interpreter is
+ :term:`shutting down <interpreter shutdown>`, :const:`False` otherwise.
+
+ .. versionadded:: 3.5
+
+
.. data:: last_type
last_value
last_traceback
diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst
index cc883b1b51..2e16077b8a 100644
--- a/Doc/library/weakref.rst
+++ b/Doc/library/weakref.rst
@@ -258,7 +258,7 @@ These method have the same issues as the and :meth:`keyrefs` method of
are called in reverse order of creation.
A finalizer will never invoke its callback during the later part of
- the interpreter shutdown when module globals are liable to have
+ the :term:`interpreter shutdown` when module globals are liable to have
been replaced by :const:`None`.
.. method:: __call__()
@@ -527,8 +527,8 @@ follows::
Starting with Python 3.4, :meth:`__del__` methods no longer prevent
reference cycles from being garbage collected, and module globals are
-no longer forced to :const:`None` during interpreter shutdown. So this
-code should work without any issues on CPython.
+no longer forced to :const:`None` during :term:`interpreter shutdown`.
+So this code should work without any issues on CPython.
However, handling of :meth:`__del__` methods is notoriously implementation
specific, since it depends on internal details of the interpreter's garbage
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 9ac105fe38..ec2eaf3bab 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -744,6 +744,27 @@ class SysModuleTest(unittest.TestCase):
c = sys.getallocatedblocks()
self.assertIn(c, range(b - 50, b + 50))
+ def test_is_finalizing(self):
+ self.assertIs(sys.is_finalizing(), False)
+ # Don't use the atexit module because _Py_Finalizing is only set
+ # after calling atexit callbacks
+ code = """if 1:
+ import sys
+
+ class AtExit:
+ is_finalizing = sys.is_finalizing
+ print = print
+
+ def __del__(self):
+ self.print(self.is_finalizing(), flush=True)
+
+ # Keep a reference in the __main__ module namespace, so the
+ # AtExit destructor will be called at Python exit
+ ref = AtExit()
+ """
+ rc, stdout, stderr = assert_python_ok('-c', code)
+ self.assertEqual(stdout.rstrip(), b'True')
+
@test.support.cpython_only
class SizeofTest(unittest.TestCase):
diff --git a/Misc/NEWS b/Misc/NEWS
index a9ffe84b35..840055084d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -194,6 +194,9 @@ Core and Builtins
Library
-------
+- Issue #22696: Add function :func:`sys.is_finalizing` to know about
+ interpreter shutdown.
+
- Issue #16043: Add a default limit for the amount of data xmlrpclib.gzip_decode
will return. This resolves CVE-2013-1753.
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 6fb882f015..aa4046ff93 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1121,6 +1121,16 @@ PyDoc_STRVAR(sys_clear_type_cache__doc__,
"_clear_type_cache() -> None\n\
Clear the internal type lookup cache.");
+static PyObject *
+sys_is_finalizing(PyObject* self, PyObject* args)
+{
+ return PyBool_FromLong(_Py_Finalizing != NULL);
+}
+
+PyDoc_STRVAR(is_finalizing_doc,
+"is_finalizing()\n\
+Return True if Python is exiting.");
+
static PyMethodDef sys_methods[] = {
/* Might as well keep this in alphabetic order */
@@ -1167,6 +1177,7 @@ static PyMethodDef sys_methods[] = {
getwindowsversion_doc},
#endif /* MS_WINDOWS */
{"intern", sys_intern, METH_VARARGS, intern_doc},
+ {"is_finalizing", sys_is_finalizing, METH_NOARGS, is_finalizing_doc},
#ifdef USE_MALLOPT
{"mdebug", sys_mdebug, METH_VARARGS},
#endif