[Python-Dev] results of id() and weakref.getweakrefs() sometimes break on object resurrection

Stefan Richthofer stefan.richthofer at gmx.de
Mon Oct 27 14:36:31 CET 2014

Your test program performs no resurrection of x.

Interestingly, it does not change behavior if you write

class X(object):
     def __del__(self):
         X.x = self
         print ref()

(Thanks for making me aware of this! My test-case was already
initially the more complex one given below)

But if the resurrection occurs indirectly, the weakref persists:
(I refined it to old-style class, because Jython will support new-style
class finalizers only from 2.7. beta 4 onwards, i.e. the test would be
pointless with any current release)

import weakref, time, gc
class ReferentDummy():

class X():
     def __del__(self):
         X.y = self.z
         print "__del__: "+str(ref())

x = X()
x2 = ReferentDummy()
ref = weakref.ref(x2)
x.z = x2
del x2
del x #Everything is now deleted, isn't it?
gc.collect() #needed in Jython-case
time.sleep(0.2) #wait for Java's async gc to finnish
print ref()
print weakref.getweakrefs(X.y)

---------------CPython output:
__del__: <__main__.ReferentDummy instance at 0x7fd2603e1950>
<__main__.ReferentDummy instance at 0x7fd2603e1950>
[<weakref at 0x7fd2603d2c00; to 'instance' at 0x7fd2603e1950>]

---------------Jython 2.7 beta 3 output:
__del__: None

One can surely argue x2 has never been dead, or see it as "it was killed 
along with x and
then resurrected by x". Jython clearly takes the second point of view 
and also clears weakrefs
to x.z, while CPython does not. Yes, these details probably hardly 
matter in practice (however
could cause subtle bugs when porting complex stuff from CPython to 
Jython), but since I try to
bridge it, I have to look into this more carefully.



On 10/26/2014 06:44 PM, Armin Rigo wrote:
> Hi Stefan,
> On 26 October 2014 02:50, Stefan Richthofer <Stefan.Richthofer at gmx.de> wrote:
>> It appears weakrefs are only cleared if this is done by gc (where no
>> resurrection can happen anyway). If a resurrection-performing-__del__ is
>> just called by ref-count-drop-to-0, weakrefs persist -
> How do you reach this conclusion?  The following test program seems to
> show the opposite, by printing None on Python 2.7.6:
>      import weakref
>     class X(object):
>          def __del__(self):
>              print ref()
>      x = X()
>      ref = weakref.ref(x)
>      del x
> A bientôt,
> Armin.

More information about the Python-Dev mailing list