Skip to content

Commit 5db1bb8

Browse files
committed
Issue #22696: Add function :func:sys.is_finalizing to know about interpreter shutdown.
1 parent b9859da commit 5db1bb8

File tree

7 files changed

+62
-6
lines changed

7 files changed

+62
-6
lines changed

Doc/glossary.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,19 @@ Glossary
402402
than compiled ones, though their programs generally also run more
403403
slowly. See also :term:`interactive`.
404404

405+
interpreter shutdown
406+
When asked to shut down, the Python interpreter enters a special phase
407+
where it gradually releases all allocated resources, such as modules
408+
and various critical internal structures. It also makes several calls
409+
to the :term:`garbage collector <garbage collection>`. This can trigger
410+
the execution of code in user-defined destructors or weakref callbacks.
411+
Code executed during the shutdown phase can encounter various
412+
exceptions as the resources it relies on may not function anymore
413+
(common examples are library modules or the warnings machinery).
414+
415+
The main reason for interpreter shutdown is that the ``__main__`` module
416+
or the script being run has finished executing.
417+
405418
iterable
406419
An object capable of returning its members one at a time. Examples of
407420
iterables include all sequence types (such as :class:`list`, :class:`str`,

Doc/library/gc.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ values but should not rebind them):
186186
added to this list rather than freed.
187187

188188
.. versionchanged:: 3.2
189-
If this list is non-empty at interpreter shutdown, a
189+
If this list is non-empty at :term:`interpreter shutdown`, a
190190
:exc:`ResourceWarning` is emitted, which is silent by default. If
191191
:const:`DEBUG_UNCOLLECTABLE` is set, in addition all uncollectable objects
192192
are printed.
@@ -252,8 +252,8 @@ The following constants are provided for use with :func:`set_debug`:
252252
to the ``garbage`` list.
253253

254254
.. versionchanged:: 3.2
255-
Also print the contents of the :data:`garbage` list at interpreter
256-
shutdown, if it isn't empty.
255+
Also print the contents of the :data:`garbage` list at
256+
:term:`interpreter shutdown`, if it isn't empty.
257257

258258
.. data:: DEBUG_SAVEALL
259259

Doc/library/sys.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,14 @@ always available.
718718
value of :func:`intern` around to benefit from it.
719719

720720

721+
.. function:: is_finalizing()
722+
723+
Return :const:`True` if the Python interpreter is
724+
:term:`shutting down <interpreter shutdown>`, :const:`False` otherwise.
725+
726+
.. versionadded:: 3.5
727+
728+
721729
.. data:: last_type
722730
last_value
723731
last_traceback

Doc/library/weakref.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ These method have the same issues as the and :meth:`keyrefs` method of
258258
are called in reverse order of creation.
259259

260260
A finalizer will never invoke its callback during the later part of
261-
the interpreter shutdown when module globals are liable to have
261+
the :term:`interpreter shutdown` when module globals are liable to have
262262
been replaced by :const:`None`.
263263

264264
.. method:: __call__()
@@ -527,8 +527,8 @@ follows::
527527

528528
Starting with Python 3.4, :meth:`__del__` methods no longer prevent
529529
reference cycles from being garbage collected, and module globals are
530-
no longer forced to :const:`None` during interpreter shutdown. So this
531-
code should work without any issues on CPython.
530+
no longer forced to :const:`None` during :term:`interpreter shutdown`.
531+
So this code should work without any issues on CPython.
532532

533533
However, handling of :meth:`__del__` methods is notoriously implementation
534534
specific, since it depends on internal details of the interpreter's garbage

Lib/test/test_sys.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,27 @@ def test_getallocatedblocks(self):
744744
c = sys.getallocatedblocks()
745745
self.assertIn(c, range(b - 50, b + 50))
746746

747+
def test_is_finalizing(self):
748+
self.assertIs(sys.is_finalizing(), False)
749+
# Don't use the atexit module because _Py_Finalizing is only set
750+
# after calling atexit callbacks
751+
code = """if 1:
752+
import sys
753+
754+
class AtExit:
755+
is_finalizing = sys.is_finalizing
756+
print = print
757+
758+
def __del__(self):
759+
self.print(self.is_finalizing(), flush=True)
760+
761+
# Keep a reference in the __main__ module namespace, so the
762+
# AtExit destructor will be called at Python exit
763+
ref = AtExit()
764+
"""
765+
rc, stdout, stderr = assert_python_ok('-c', code)
766+
self.assertEqual(stdout.rstrip(), b'True')
767+
747768

748769
@test.support.cpython_only
749770
class SizeofTest(unittest.TestCase):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ Core and Builtins
194194
Library
195195
-------
196196

197+
- Issue #22696: Add function :func:`sys.is_finalizing` to know about
198+
interpreter shutdown.
199+
197200
- Issue #16043: Add a default limit for the amount of data xmlrpclib.gzip_decode
198201
will return. This resolves CVE-2013-1753.
199202

Python/sysmodule.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,16 @@ PyDoc_STRVAR(sys_clear_type_cache__doc__,
11211121
"_clear_type_cache() -> None\n\
11221122
Clear the internal type lookup cache.");
11231123

1124+
static PyObject *
1125+
sys_is_finalizing(PyObject* self, PyObject* args)
1126+
{
1127+
return PyBool_FromLong(_Py_Finalizing != NULL);
1128+
}
1129+
1130+
PyDoc_STRVAR(is_finalizing_doc,
1131+
"is_finalizing()\n\
1132+
Return True if Python is exiting.");
1133+
11241134

11251135
static PyMethodDef sys_methods[] = {
11261136
/* Might as well keep this in alphabetic order */
@@ -1167,6 +1177,7 @@ static PyMethodDef sys_methods[] = {
11671177
getwindowsversion_doc},
11681178
#endif /* MS_WINDOWS */
11691179
{"intern", sys_intern, METH_VARARGS, intern_doc},
1180+
{"is_finalizing", sys_is_finalizing, METH_NOARGS, is_finalizing_doc},
11701181
#ifdef USE_MALLOPT
11711182
{"mdebug", sys_mdebug, METH_VARARGS},
11721183
#endif

0 commit comments

Comments
 (0)