__del__ methods

J

Jason Baker

I have a class that I need to do some finalization on when it dies. I
know I can use the __del__ method, but I seem to recall that it
impedes garbage collection. Is this the case?

(keep in mind that my code aims to be compatible with python 2.3 to
python 2.5)
 
M

Marc 'BlackJack' Rintsch

I have a class that I need to do some finalization on when it dies. I
know I can use the __del__ method, but I seem to recall that it
impedes garbage collection. Is this the case?

`__del__()` is not a deterministic destructor. So forget about reliable
automatic clean up. Do it yourself with an explicit call to a `close()`
method or something like that.

Ciao,
Marc 'BlackJack' Rintsch
 
J

Jason Baker

`__del__()` is not a deterministic destructor.  So forget about reliable
automatic clean up.  Do it yourself with an explicit call to a `close()`
method or something like that.

Ciao,
        Marc 'BlackJack' Rintsch

I don't necessarily need deterministic cleanup. And I plan on doing
something like a close() method as well. But I'd just like to make
sure nothing slips between the cracks. :)
 
M

Marc 'BlackJack' Rintsch

I don't necessarily need deterministic cleanup. And I plan on doing
something like a close() method as well. But I'd just like to make
sure nothing slips between the cracks. :)

`__del__()` isn't guaranteed to be called *at all*, so can't make sure
nothing slips between the cracks with it.

Ciao,
Marc 'BlackJack' Rintsch
 
R

Raymond Hettinger

I have a class that I need to do some finalization on when it dies.  I
know I can use the __del__ method, but I seem to recall that it
impedes garbage collection.  Is this the case?

FWIW, I know a good number of top notch Python programmers
who have programmed happily for years without ever using
__del__. There are ways to get it to work for you, but
it may be the smart thing to pretend that you've never
heard of it.

Raymond
 
M

Miles

I have a class that I need to do some finalization on when it dies. I
know I can use the __del__ method, but I seem to recall that it
impedes garbage collection. Is this the case?

Yes.

"Objects that have __del__() methods and are part of a reference cycle
cause the entire reference cycle to be uncollectable, including
objects not necessarily in the cycle but reachable only from it.
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."

The uncollectable objects are stored in gc.garbage and will not be
freed until their reference cycles are broken and they are removed
from that list.

http://docs.python.org/lib/module-gc.html

-Miles
 
R

Robert Rawlins

Yes.
"Objects that have __del__() methods and are part of a reference cycle
cause the entire reference cycle to be uncollectable, including
objects not necessarily in the cycle but reachable only from it.
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."

The uncollectable objects are stored in gc.garbage and will not be
freed until their reference cycles are broken and they are removed
from that list.

Ok, guys,

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.

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

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?

Cheers,

Robert
 
R

Robert Rawlins

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

Ok, well that's good to know. :)
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.

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)


def __init__(self):
self._track = Track(self)

I like this idea, I can definitely see the benefits to working with this
concept. One things I will take this quick opportunity to ask, even though
it's a little OT:

What is the benefit of extending the base 'object' class? What does that
give me that en empty, non subclassed object doesn't?
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).

Yes, that's a very nice concept and like you say gives you quite a nice
visual reference of what objects are and aren't being destroyed.

Cheers Duncan,

Robert
 
B

Bruno Desthuilliers

Robert Rawlins a écrit :
Thanks Ben, I'll be sure to read through these. I also read through
this http://www.geocities.com/foetsch/python/new_style_classes.htm
earlier this morning which was also a nice little resource.

Just about all of it makes sense at the moment, apart from the new
constructor types which are constructors at a class level opposed to
at instance level. I found this a little confusing but who knows.

Are you talking about the __new__ method ? Or about metaclasses ?
 
R

Robert Rawlins

In Python 2.x, "classic" classes (which are not part of the unified
type hierarchy) are deprecated, and exist only for backward
compatibility with old code.

You need to create "new-style" classes
<URL:http://www.python.org/doc/newstyle/> by inheriting from some
class that is part of the unified type hierarchy; if there is no
obvious candidate, 'object' is the recommended choice.

Thanks Ben,

This isn’t something I'd seen before (god that makes me feel stupid). I've always based my code off the odd example that's dotted around and hadn’t ever done any proper reading on these new type classes.

I've done a little reading this morning and really love a great deal of the concepts, I'll be upgrading my app to this spec in the next few days.

Robert
 
R

Robert Rawlins

Time to fix that, then, with some documentation
<URL:http://www.python.org/doc/>, and by working through the Python
tutorial <URL:http://www.python.org/doc/tut/>.

Thanks Ben, I'll be sure to read through these. I also read through this http://www.geocities.com/foetsch/python/new_style_classes.htm earlier this morning which was also a nice little resource.

Just about all of it makes sense at the moment, apart from the new constructor types which are constructors at a class level opposed to at instance level. I found this a little confusing but who knows.

Presumably this is where you would deal with setting things which exist in every instance of a class, and properties that can vary from instance to instance go into the standard __init_(), have I got that right?

Cheers Ben,

Robert
 
R

Robert Rawlins

Are you talking about the __new__ method ? Or about metaclasses ?

Sorry Bruno, I should have made that a little clearer. I was talking about the __new__ method.

Cheers mate,

Robert
 

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,981
Messages
2,570,187
Members
46,730
Latest member
AudryNolan

Latest Threads

Top