From 1f8898a5916b942c86ee8716c37d2db388e7bf2f Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Tue, 26 Mar 2013 01:59:56 +0200 Subject: #17323: The "[X refs, Y blocks]" printed by debug builds has been disabled by default. It can be re-enabled with the `-X showrefcount` option. --- Doc/using/cmdline.rst | 14 +++++++++++--- Lib/test/test_cmd_line.py | 28 ++++++++++++++++++++++++++++ Misc/NEWS | 3 +++ Python/pythonrun.c | 24 ++++++++++++++++++++---- 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 2703684..adb3739 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -358,13 +358,21 @@ Miscellaneous options .. cmdoption:: -X Reserved for various implementation-specific options. CPython currently - defines just one, you can use ``-X faulthander`` to enable - :data:`faulthandler`. It also allows to pass arbitrary values and retrieve - them through the :data:`sys._xoptions` dictionary. + defines two possible values: + + * ``-X faulthander`` to enable :mod:`faulthandler`; + * ``-X showrefcount`` to enable the output of the total reference count + and memory blocks (only works on debug builds); + + It also allows to pass arbitrary values and retrieve them through the + :data:`sys._xoptions` dictionary. .. versionchanged:: 3.2 It is now allowed to pass :option:`-X` with CPython. + .. versionadded:: 3.4 + The ``-X showrefcount`` option. + Options you shouldn't use ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 6684e51..2551ab5 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -62,6 +62,34 @@ class CmdLineTest(unittest.TestCase): opts = eval(out.splitlines()[0]) self.assertEqual(opts, {'a': True, 'b': 'c,d=e'}) + def test_showrefcount(self): + def run_python(*args): + # this is similar to assert_python_ok but doesn't strip + # the refcount from stderr. It can be replaced once + # assert_python_ok stops doing that. + cmd = [sys.executable] + cmd.extend(args) + PIPE = subprocess.PIPE + p = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE) + out, err = p.communicate() + p.stdout.close() + p.stderr.close() + rc = p.returncode + self.assertEqual(rc, 0) + return rc, out, err + code = 'import sys; print(sys._xoptions)' + # normally the refcount is hidden + rc, out, err = run_python('-c', code) + self.assertEqual(out.rstrip(), b'{}') + self.assertEqual(err, b'') + # "-X showrefcount" shows the refcount, but only in debug builds + rc, out, err = run_python('-X', 'showrefcount', '-c', code) + self.assertEqual(out.rstrip(), b"{'showrefcount': True}") + if hasattr(sys, 'gettotalrefcount'): # debug build + self.assertRegex(err, br'^\[\d+ refs, \d+ blocks\]') + else: + self.assertEqual(err, b'') + def test_run_module(self): # Test expected operation of the '-m' switch # Switch needs an argument diff --git a/Misc/NEWS b/Misc/NEWS index edda541..e9261c5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1? Core and Builtins ----------------- +- Issue #17323: The "[X refs, Y blocks]" printed by debug builds has been + disabled by default. It can be re-enabled with the `-X showrefcount` option. + - Issue #17522: Add the PyGILState_Check() API. - Issue #16475: Support object instancing, recursion and interned strings diff --git a/Python/pythonrun.c b/Python/pythonrun.c index f0d8550..751008a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -35,13 +35,29 @@ #define PATH_MAX MAXPATHLEN #endif +#ifdef Py_REF_DEBUG +void _print_total_refs() { + PyObject *xoptions, *key, *value; + xoptions = PySys_GetXOptions(); + if (xoptions == NULL) + return; + key = PyUnicode_FromString("showrefcount"); + if (key == NULL) + return; + value = PyDict_GetItem(xoptions, key); + Py_DECREF(key); + if (value == Py_True) + fprintf(stderr, + "[%" PY_FORMAT_SIZE_T "d refs, " + "%" PY_FORMAT_SIZE_T "d blocks]\n", + _Py_GetRefTotal(), _Py_GetAllocatedBlocks()); +} +#endif + #ifndef Py_REF_DEBUG #define PRINT_TOTAL_REFS() #else /* Py_REF_DEBUG */ -#define PRINT_TOTAL_REFS() fprintf(stderr, \ - "[%" PY_FORMAT_SIZE_T "d refs, " \ - "%" PY_FORMAT_SIZE_T "d blocks]\n", \ - _Py_GetRefTotal(), _Py_GetAllocatedBlocks()) +#define PRINT_TOTAL_REFS() _print_total_refs() #endif #ifdef __cplusplus -- cgit v0.12