diff -r f2ce9603346c Lib/test/test_sys.py --- a/Lib/test/test_sys.py Wed Oct 22 12:33:23 2014 +0200 +++ b/Lib/test/test_sys.py Wed Oct 22 14:29:45 2014 +0200 @@ -744,6 +744,26 @@ class SysModuleTest(unittest.TestCase): c = sys.getallocatedblocks() self.assertIn(c, range(b - 50, b + 50)) + @test.support.cpython_only + def test_is_finalizing(self): + # Don't use the atexit module because _Py_Finalizing is only set + # after calling atexit callbacks + code = textwrap.dedent(''' + import sys + + class AtExit: + is_finalizing = sys._is_finalizing + + def __del__(self): + print(self.is_finalizing(), flush=True) + + # Keep a reference in the 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 -r f2ce9603346c Python/sysmodule.c --- a/Python/sysmodule.c Wed Oct 22 12:33:23 2014 +0200 +++ b/Python/sysmodule.c Wed Oct 22 14:29:45 2014 +0200 @@ -1116,6 +1116,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 is Python is exiting."); + static PyMethodDef sys_methods[] = { /* Might as well keep this in alphabetic order */ @@ -1191,6 +1201,8 @@ static PyMethodDef sys_methods[] = { {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc}, {"_debugmallocstats", sys_debugmallocstats, METH_NOARGS, debugmallocstats_doc}, + {"_is_finalizing", sys_is_finalizing, METH_NOARGS, + is_finalizing_doc}, {NULL, NULL} /* sentinel */ };