Base class deleted before subclass during python __del__ processing
- by Oddthinking
Context
I am aware that if I ask a question about Python destructors, the standard argument will be to use contexts instead. Let me start by explaining why I am not doing that.
I am writing a subclass to logging.Handler. When an instance is closed, it posts a sentinel value to a Queue.Queue. If it doesn't, a second thread will be left running forever, waiting for Queue.Queue.get() to complete.
I am writing this with other developers in mind, so I don't want a failure to call close() on a handler object to cause the program to hang.
Therefore, I am adding a check in __del__() to ensure the object was closed properly.
I understand circular references may cause it to fail in some circumstances. There's not a lot I can do about that.
Problem
Here is some simple example code:
explicit_delete = True
class Base:
def __del__(self):
print "Base class cleaning up."
class Sub(Base):
def __del__(self):
print "Sub-class cleaning up."
Base.__del__(self)
x = Sub()
if explicit_delete:
del x
print "End of thread"
When I run this I get, as expected:
Sub-class cleaning up.
Base class cleaning up.
End of thread
If I set explicit_delete to False in the first line, I get:
End of thread
Sub-class cleaning up.
Exception AttributeError: "'NoneType' object has no attribute '__del__'" in <bound method Sub.__del__ of <__main__.Sub instance at 0x00F0B698>> ignored
It seems the definition of Base is removed before the x._del_() is called.
The Python Documentation on _del_() warns that the subclass needs to call the base-class to get a clean deletion, but here that appears to be impossible.
Can you see where I made a bad step?