[Python-Dev] __del__ is not called after creating a new reference

2017年3月20日 10:33:16 -0700

Hello,
I already tried to ask on python-list, see
https://mail.python.org/pipermail/python-list/2017-March/720037.html
but it seems that this list is not for technical questions.
Let me resend my question to python-dev. Please tell me if I should not spam
this list with newbiesh questions, and thanks in advance.
---------------------------------------------------------------------------
I started to learn python a few days ago and I am trying to understand what
__del__() actually does. https://docs.python.org/3/reference/datamodel.html
says:
 object.__del__(self)
 ...
 Note that it is possible (though not recommended!) for the __del__()
 method to postpone destruction of the instance by creating a new
 reference to it. It may then be called at a later time when this new
 reference is deleted.
However, this trivial test-case
 class C:
 def __del__(self):
 print("DEL")
 global X
 X = self
 C()
 print(X)
 X = 0
 print(X)
shows that __del__ is called only once, it is not called again after "X = 0":
 DEL
 <__main__.C object at 0x7f067695f4a8>
 0
 
(Just in case, I verified later that this object actually goes away and its
 memory is freed, so the problem is not that it still has a reference).
I've cloned https://github.com/python/cpython.git and everything looks clear
at first glance (but let me repeat that I am very new to python):
 PyObject_CallFinalizerFromDealloc() calls PyObject_CallFinalizer()
 which finally calls "__del__" method in slot_tp_finalize(), then it
 notices that "X = self" creates the new reference and does:
 /* tp_finalize resurrected it! Make it look like the original Py_DECREF
 * never happened.
 */
 refcnt = self->ob_refcnt;
 _Py_NewReference(self);
 self->ob_refcnt = refcnt;
However, PyObject_CallFinalizer() also does _PyGC_SET_FINALIZED(self, 1)
and that is why __del__ is not called again after "X = 0":
 /* tp_finalize should only be called once. */
 if (PyType_IS_GC(tp) && _PyGC_FINALIZED(self))
 return;
The comment and the code are very explicit, so this does nt look like a
bug in cpython.
Probably the docs should be fixed?
Or this code is actually wrong? The test-case works as documented if I
remove _PyGC_SET_FINALIZED() in PyObject_CallFinalizer() or add another
_PyGC_SET_FINALIZED(self, 0) into PyObject_CallFinalizerFromDealloc()
after _Py_NewReference(self), but yes, yes, I understand that this is
not correct and won't really help.
Oleg.
_______________________________________________
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to