Dynamically change __del__

N

Nikolaus Rath

Hi,

I'm trying to be very clever:

class tst(object):
def destroy(self):
print 'Cleaning up.'
self.__del__ = lambda: None
def __del__(self):
raise RuntimeError('Instance destroyed without running destroy! Hell may break loose!')

However, it doesn't work:

In [2]: t = tst()

In [3]: t = None
Exception RuntimeError: RuntimeError('Instance destroyed without running destroy! Hell may break loose!',) in <bound method tst.__del__ of <__main__.tst object at 0x978566c>> ignored

In [4]: t = tst()

In [5]: t.destroy()
Cleaning up.

In [6]: t = None
Exception RuntimeError: RuntimeError('Instance destroyed without running destroy! Hell may break loose!',) in <bound method tst.__del__ of <__main__.tst object at 0x978566c>> ignored

$ python -V
Python 2.6.4


Apparently Python calls the class attribute __del__ rather than the
instance's __del__ attribute. Is that a bug or a feature? Is there any
way to implement the desired functionality without introducing an
additional destroy_has_been_called attribute?


(I know that invocation of __del__ is unreliable, this is just an
additional safeguard to increase the likelihood of bugs to get noticed).



Best,

-Nikolaus
 
L

Lie Ryan

Hi,

I'm trying to be very clever:
Apparently Python calls the class attribute __del__ rather than the
instance's __del__ attribute. Is that a bug or a feature? Is there any
way to implement the desired functionality without introducing an
additional destroy_has_been_called attribute?


(I know that invocation of __del__ is unreliable, this is just an
additional safeguard to increase the likelihood of bugs to get noticed).

All Exception in __del__ is ignored for various reasons. It's safer if
you call destroy from inside __del__() so you cannot forget to remember
to call it manually.

def __del__(self):
self.destroy()
 
J

Jerry Hill

Apparently Python calls the class attribute __del__ rather than the
instance's __del__ attribute. Is that a bug or a feature? Is there any
way to implement the desired functionality without introducing an
additional destroy_has_been_called attribute?

It's a documented feature:
http://docs.python.org/reference/datamodel.html#new-style-special-lookup

I'm not aware of a way to get around it, so I think you'll need to
fall back to checking a flag in the class's __del__ method.
 
P

Peter Otten

Nikolaus said:
Apparently Python calls the class attribute __del__ rather than the
instance's __del__ attribute. Is that a bug or a feature? Is there any
way to implement the desired functionality without introducing an
additional destroy_has_been_called attribute?

For newstyle classes __special__() methods are always looked up in the
class, never in the instance.

Your best bet is probably to manage the lifetime of the instance explicitly
with try...finally or a context manager:
.... def close(self):
.... print "Cleaning up."
........ print t
....
<__main__.T object at 0x7fc50c1e61d0>
Cleaning up.

Alternatively you can try and cook up something with weakref.ref and a
callback.

Peter
 
L

Lie Ryan

All Exception in __del__ is ignored for various reasons. It's safer if
you call destroy from inside __del__() so you cannot forget to remember
to call it manually.

def __del__(self):
self.destroy()

Never mind that, just realized you're asking for a different thing.
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top