[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():
pass
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
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.
Best,
Stefan
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