Python leaks in cyclic garbage collection

M

moerchendiser2k3

Hi, I have some problems with Python and the garbage collection. In
the following piece of code I create a simple gargabe collection but I
am still wondering why the finalizers are never called - at least on
exit of Py they should be called somehow. What do I miss here? I know,
there is no deterministic way how to resolve this though.

class Foo():

def __init__(self):
self.b=Bar(self)

def __del__(self):
print "Free Foo"

class Bar():
def __init__(self, f):
self.f=f

def __del__(self):
print "Free Bar"

f=Foo()
print f
 
C

Chris Rebert

Hi, I have some problems with Python and the garbage collection. In
the following piece of code I create a simple gargabe collection but I
am still wondering why the finalizers are never called - at least on
exit of Py they should be called somehow. What do I miss here?
<code snippet involving circularly-referenced objects with __del__
methods snipped>

Read The Fine Manual (all emphases added):

http://docs.python.org/reference/datamodel.html#object.__del__ :
"***It is not guaranteed that __del__() methods are called for objects
that still exist when the interpreter exits.***"
"Note: [...] x.__del__() — [...] is only called when x‘s reference
count reaches zero. Some common situations that may prevent the
reference count of an object from going to zero include: circular
references between objects [...] Circular references which are garbage
are detected when the option cycle detector is enabled (it’s on by
default), ***but can only be cleaned up if there are no Python-level
__del__() methods involved***. Refer to the documentation for the `gc`
module for more information about how __del__() methods are handled by
the cycle detector, particularly the description of the `garbage`
value."

And following the pointer to gc.garbage's docs:
http://docs.python.org/library/gc.html#gc.garbage :
"Objects that have __del__() methods and are part of a reference cycle
***cause the entire reference cycle to be uncollectable*** [...]
Python doesn’t collect such cycles automatically because, in general,
it isn’t possible for Python to guess a safe order in which to run the
__del__() methods. [...] It’s generally better to avoid the issue by
not creating cycles containing objects with __del__() methods"

Cheers,
Chris
 
S

Steven D'Aprano

And following the pointer to gc.garbage's docs:
http://docs.python.org/library/gc.html#gc.garbage : "Objects that have
__del__() methods and are part of a reference cycle ***cause the entire
reference cycle to be uncollectable*** [...] Python doesn’t collect such
cycles automatically because, in general, it isn’t possible for Python
to guess a safe order in which to run the __del__() methods. [...] It’s
generally better to avoid the issue by not creating cycles containing
objects with __del__() methods"

Another solution is to manually break the cycle, perhaps by providing a
"close" method, and requiring the caller to use it.
 
A

Andrea Crotti

Il giorno 19/feb/2011, alle ore 05.10, moerchendiser2k3 ha scritto:
Hi, I have some problems with Python and the garbage collection. In
the following piece of code I create a simple gargabe collection but I
am still wondering why the finalizers are never called - at least on
exit of Py they should be called somehow. What do I miss here? I know,
there is no deterministic way how to resolve this though.

class Foo():

def __init__(self):
self.b=Bar(self)

def __del__(self):
print "Free Foo"

class Bar():
def __init__(self, f):
self.f=f

def __del__(self):
print "Free Bar"

f=Foo()
print f

Wild guess:
maybe when python exits they are called but sys.stdout has already been closed and nothing gets written on it anymore.
 
N

n00m

Wild guess:
maybe when python exits they are called but sys.stdout has already been closed and nothing gets written on it anymore.

Certainly NOT.


class Foo():
def __init__(self):
self.b = Bar(self)
def __del__(self):
print "Free Foo"

class Bar():
def __init__(self, f):
self.f = f
def __del__(self):
print "Free Bar"


f = Foo()
print f.b.f.b.f.b.f.b.f.b.f.b.f.b.f.b.f
print f.b.f.b.f.b.f.b.f.b.f.b.f.b.f.b.f.b



*********Console output:***********

<__main__.Foo instance at 0x00AF7328>
<__main__.Bar instance at 0x00AF7350>

D:\v3>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top