Hey #python-dev,

I'd like to ask your opinion on this change; I think it should be reverted
or at least made silent by default.  Basically, it prints a warning like

      gc: 2 uncollectable objects at shutdown:
          Use gc.set_debug(gc.DEBUG_UNCOLLECTABLE) to list them.

at interpreter shutdown if gc.garbage is nonempty.

IMO this runs contrary to the decision we made when DeprecationWarnings were
made silent by default: it spews messages not only at developers, but also at
users, who don't need it and probably are going to be quite confused by it,
assuming it came from their console application (imagine Mercurial printing
this).

Opinions?

Georg


Am 09.08.2010 00:18, schrieb antoine.pitrou:
> Author: antoine.pitrou
> Date: Mon Aug  9 00:18:46 2010
> New Revision: 83861
> 
> Log:
> Issue #477863: Print a warning at shutdown if gc.garbage is not empty.
> 
> 
> 
> Modified:
>    python/branches/py3k/Doc/library/gc.rst
>    python/branches/py3k/Doc/whatsnew/3.2.rst
>    python/branches/py3k/Include/pythonrun.h
>    python/branches/py3k/Lib/test/test_gc.py
>    python/branches/py3k/Misc/NEWS
>    python/branches/py3k/Modules/gcmodule.c
>    python/branches/py3k/Python/pythonrun.c
> 
> Modified: python/branches/py3k/Doc/library/gc.rst
> ==============================================================================
> --- python/branches/py3k/Doc/library/gc.rst   (original)
> +++ python/branches/py3k/Doc/library/gc.rst   Mon Aug  9 00:18:46 2010
> @@ -177,6 +177,15 @@
>     If :const:`DEBUG_SAVEALL` is set, then all unreachable objects will be 
> added to
>     this list rather than freed.
>  
> +   .. versionchanged:: 3.2
> +      If this list is non-empty at interpreter shutdown, a warning message
> +      gets printed:
> +
> +   ::
> +
> +      gc: 2 uncollectable objects at shutdown:
> +          Use gc.set_debug(gc.DEBUG_UNCOLLECTABLE) to list them.
> +
>  The following constants are provided for use with :func:`set_debug`:
>  
>  
> @@ -197,6 +206,9 @@
>     reachable but cannot be freed by the collector).  These objects will be 
> added to
>     the ``garbage`` list.
>  
> +   .. versionchanged:: 3.2
> +      Also print the contents of the :data:`garbage` list at interpreter
> +      shutdown (rather than just its length), if it isn't empty.
>  
>  .. data:: DEBUG_SAVEALL
>  
> 
> Modified: python/branches/py3k/Doc/whatsnew/3.2.rst
> ==============================================================================
> --- python/branches/py3k/Doc/whatsnew/3.2.rst (original)
> +++ python/branches/py3k/Doc/whatsnew/3.2.rst Mon Aug  9 00:18:46 2010
> @@ -119,6 +119,11 @@
>  * The :class:`ftplib.FTP` class now supports the context manager protocol
>    (Contributed by Tarek Ziadé and Giampaolo Rodolà; :issue:`4972`.)
>  
> +* A warning message will now get printed at interpreter shutdown if
> +  the :data:`gc.garbage` list isn't empty.  This is meant to make the
> +  programmer aware that his code contains object finalization issues.
> +  (Added by Antoine Pitrou; :issue:`477863`.)
> +
>  * The :func:`shutil.copytree` function has two new options:
>  
>    * *ignore_dangling_symlinks*: when ``symlinks=False`` (meaning that the
> 
> Modified: python/branches/py3k/Include/pythonrun.h
> ==============================================================================
> --- python/branches/py3k/Include/pythonrun.h  (original)
> +++ python/branches/py3k/Include/pythonrun.h  Mon Aug  9 00:18:46 2010
> @@ -148,6 +148,7 @@
>  PyAPI_FUNC(void) PyByteArray_Fini(void);
>  PyAPI_FUNC(void) PyFloat_Fini(void);
>  PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
> +PyAPI_FUNC(void) _PyGC_Fini(void);
>  
>  /* Stuff with no proper home (yet) */
>  PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, char *);
> 
> Modified: python/branches/py3k/Lib/test/test_gc.py
> ==============================================================================
> --- python/branches/py3k/Lib/test/test_gc.py  (original)
> +++ python/branches/py3k/Lib/test/test_gc.py  Mon Aug  9 00:18:46 2010
> @@ -1,5 +1,5 @@
>  import unittest
> -from test.support import verbose, run_unittest
> +from test.support import verbose, run_unittest, strip_python_stderr
>  import sys
>  import gc
>  import weakref
> @@ -466,6 +466,42 @@
>              # would be damaged, with an empty __dict__.
>              self.assertEqual(x, None)
>  
> +    def test_garbage_at_shutdown(self):
> +        import subprocess
> +        code = """if 1:
> +            import gc
> +            class X:
> +                def __init__(self, name):
> +                    self.name = name
> +                def __repr__(self):
> +                    return "<X %%r>" %% self.name
> +                def __del__(self):
> +                    pass
> +
> +            x = X('first')
> +            x.x = x
> +            x.y = X('second')
> +            del x
> +            if %d:
> +                gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
> +        """
> +        def run_command(code):
> +            p = subprocess.Popen([sys.executable, "-c", code],
> +                stdout=subprocess.PIPE,
> +                stderr=subprocess.PIPE)
> +            stdout, stderr = p.communicate()
> +            self.assertEqual(p.returncode, 0)
> +            self.assertEqual(stdout.strip(), b"")
> +            return strip_python_stderr(stderr)
> +
> +        stderr = run_command(code % 0)
> +        self.assertIn(b"gc: 2 uncollectable objects at shutdown", stderr)
> +        self.assertNotIn(b"[<X 'first'>, <X 'second'>]", stderr)
> +        # With DEBUG_UNCOLLECTABLE, the garbage list gets printed
> +        stderr = run_command(code % 1)
> +        self.assertIn(b"gc: 2 uncollectable objects at shutdown", stderr)
> +        self.assertIn(b"[<X 'first'>, <X 'second'>]", stderr)
> +
>  class GCTogglingTests(unittest.TestCase):
>      def setUp(self):
>          gc.enable()
> 
> Modified: python/branches/py3k/Misc/NEWS
> ==============================================================================
> --- python/branches/py3k/Misc/NEWS    (original)
> +++ python/branches/py3k/Misc/NEWS    Mon Aug  9 00:18:46 2010
> @@ -30,6 +30,8 @@
>  Extensions
>  ----------
>  
> +- Issue #477863: Print a warning at shutdown if gc.garbage is not empty.
> +
>  - Issue #6869: Fix a refcount problem in the _ctypes extension.
>  
>  - Issue #5504: ctypes should now work with systems where mmap can't
> 
> Modified: python/branches/py3k/Modules/gcmodule.c
> ==============================================================================
> --- python/branches/py3k/Modules/gcmodule.c   (original)
> +++ python/branches/py3k/Modules/gcmodule.c   Mon Aug  9 00:18:46 2010
> @@ -1295,17 +1295,16 @@
>  
>  static struct PyModuleDef gcmodule = {
>      PyModuleDef_HEAD_INIT,
> -    "gc",
> -    gc__doc__,
> -    -1,
> -    GcMethods,
> -    NULL,
> -    NULL,
> -    NULL,
> -    NULL
> +    "gc",              /* m_name */
> +    gc__doc__,         /* m_doc */
> +    -1,                /* m_size */
> +    GcMethods,         /* m_methods */
> +    NULL,              /* m_reload */
> +    NULL,              /* m_traverse */
> +    NULL,              /* m_clear */
> +    NULL               /* m_free */
>  };
>  
> -
>  PyMODINIT_FUNC
>  PyInit_gc(void)
>  {
> @@ -1364,6 +1363,37 @@
>      return n;
>  }
>  
> +void
> +_PyGC_Fini(void)
> +{
> +    if (garbage != NULL && PyList_GET_SIZE(garbage) > 0) {
> +        PySys_WriteStderr(
> +            "gc: "
> +            "%" PY_FORMAT_SIZE_T "d uncollectable objects at shutdown:\n",
> +            PyList_GET_SIZE(garbage)
> +            );
> +        if (debug & DEBUG_UNCOLLECTABLE) {
> +            PyObject *repr = NULL, *bytes = NULL;
> +            repr = PyObject_Repr(garbage);
> +            if (!repr || !(bytes = PyUnicode_EncodeFSDefault(repr)))
> +                PyErr_WriteUnraisable(garbage);
> +            else {
> +                PySys_WriteStderr(
> +                    "    %s\n",
> +                    PyBytes_AS_STRING(bytes)
> +                    );
> +            }
> +            Py_XDECREF(repr);
> +            Py_XDECREF(bytes);
> +        }
> +        else {
> +            PySys_WriteStderr(
> +                "    Use gc.set_debug(gc.DEBUG_UNCOLLECTABLE) to list 
> them.\n"
> +                );
> +        }
> +    }
> +}
> +
>  /* for debugging */
>  void
>  _PyGC_Dump(PyGC_Head *g)
> 
> Modified: python/branches/py3k/Python/pythonrun.c
> ==============================================================================
> --- python/branches/py3k/Python/pythonrun.c   (original)
> +++ python/branches/py3k/Python/pythonrun.c   Mon Aug  9 00:18:46 2010
> @@ -404,6 +404,9 @@
>      while (PyGC_Collect() > 0)
>          /* nothing */;
>  #endif
> +    /* We run this while most interpreter state is still alive, so that
> +       debug information can be printed out */
> +    _PyGC_Fini();
>  
>      /* Destroy all modules */
>      PyImport_Cleanup();
> _______________________________________________
> Python-checkins mailing list
> python-check...@python.org
> http://mail.python.org/mailman/listinfo/python-checkins


-- 
Thus spake the Lord: Thou shalt indent with four spaces. No more, no less.
Four shall be the number of spaces thou shalt indent, and the number of thy
indenting shall be four. Eight shalt thou not indent, nor either indent thou
two, excepting that thou then proceed to four. Tabs are right out.

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to