]> granicus.if.org Git - python/commitdiff
Issue #22696: Add function :func:`sys.is_finalizing` to know about interpreter shutdown.
authorAntoine Pitrou <solipsis@pitrou.net>
Sun, 7 Dec 2014 00:28:27 +0000 (01:28 +0100)
committerAntoine Pitrou <solipsis@pitrou.net>
Sun, 7 Dec 2014 00:28:27 +0000 (01:28 +0100)
Doc/glossary.rst
Doc/library/gc.rst
Doc/library/sys.rst
Doc/library/weakref.rst
Lib/test/test_sys.py
Misc/NEWS
Python/sysmodule.c

index 92877bd896a2f16d09b15a26df9d1a790894b428..87e2d8a67246972b2dd62298a6f04fcf82d75baa 100644 (file)
@@ -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`,
index 813554206a39bc8f84361089950579b9b02162c1..d11c2e128273e3c1e60e350e3d3649e7e6d418e6 100644 (file)
@@ -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
 
index 3024086a22ab78eb08ef177e1415e62953affd61..fa125a0c9644669adc591455b710be4713bd105c 100644 (file)
@@ -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
index cc883b1b51833309d77068864c9cf00347a4dfd3..2e16077b8a6ad8173257a68f3dd5ad591719da8f 100644 (file)
@@ -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
index 9ac105fe3882f08850cb372627114637693e77f4..ec2eaf3babb758922db863aeed6d9de674f19a9b 100644 (file)
@@ -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):
index a9ffe84b35cafa9e298d01ed6e2a574f4960769f..840055084d99a696f935f2d940fa7f3d01ca1a57 100644 (file)
--- 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.
 
index 6fb882f015303e9b19d68230afe745cb8730fc95..aa4046ff93b9d8b218f2d4b1ca75a275df2b1b8b 100644 (file)
@@ -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