__del__ methods

Duncan Booth duncan.booth at invalid.invalid
Sat Jul 19 10:01:59 EDT 2008


"Robert Rawlins" <robert.rawlins at thinkbluemedia.co.uk> wrote:

> I've just recently (in the past week) started using the __del__ method
> to log class instance destruction so I can keep a track of when
> objects are created and destroyed, in order to help me trace and fix
> memory leaks. 

That sounds like an appropriate use for __del__: it won't matter that it 
may not be called when your app exits.

> 
> Are you saying that on the adverse side to this, __del__ may in fact
> be the CAUSE of a memory leak within my application?

Yes, but there is an easy work-around. If you want to track destruction of 
objects of type C then don't add a __del__ method to the C objects. Instead 
create a separate class which does nothing but track it's own desctruction 
and reference that from the class which may be leaking.

>>> class Track(object):
	def __init__(self, parent):
		self.parentid = id(parent)
		self.parenttype = type(parent).__name__
	def __del__(self):
		print "Destroyed <%s object at %s>" % (self.parenttype, 
self.parentid)

		
>>> class C(object):
	def __init__(self):
		self._track = Track(self)

		
>>> a = C()
>>> b = C()
>>> a.b = b
>>> b.a = a
>>> del a
>>> del b
>>> gc.collect()
Destroyed <C object at 18381168>
Destroyed <C object at 18382288>
19


> If this is the case and __del__ creates such a vulnerability within
> the application, and apparently isn't all that reliable anyway, why is
> it still part of the python platform?
> 
Because it does have a very few cases where it is useful. Tracking memory 
leaks may be one.

However you should also consider that __del__ only lets you log when 
objects are destroyed. Using weak references may be a more useful option as 
it will let you track which objects are not being destroyed: you can easily 
keep a dictionary of weak references to all existing objects of interest. 
Check its length periodically to see whether objects are being leaked and 
then inspect the objects themselves to see which ones have leaked.

You can use gc.get_referrers() to find everything that references a 
particular objects and gradually trace backwards until you find the problem 
reference (it is tricky though as any code which does this needs to ignore 
its own references to the object in question).




More information about the Python-list mailing list