I have a python script that contains a class.
This class has a __del__
method for usual cleanup. If I delete the class during the normal execution of the script, I want some cleanup to be done.
I also have a signal handler, that does some unusual cleanup. If the script was in the middle of executing something else when it received the signal, it needs to do some extra cleanup, followed by the regular cleanup.
I noticed there is a difference between doing del self
and self.__del__()
.
Namely, self.__del__()
calls the del
method twice.
Can you please explain why this happens?
This is a mockup script to illustrate the issue:
import sys
import signal
from optparse import OptionParser
class TestClass(object):
def __init__(self,
del_self):
self.del_self = del_self
print "__init__ with del_self = %s" % self.del_self
def __del__(self):
print "Now performing usual cleanup."
def signal_handler(self, arg_1, arg_2):
print "Received signal. Now performing unusual cleanup."
# Unusual cleanup
print "Did unusual cleanup"
if self.del_self:
print("Doing del self")
del self
else:
print("Doing self.__del__()")
self.__del__()
sys.exit(0)
if __name__ == '__main__':
arguments = sys.argv[1:]
parse = OptionParser("Test.")
parse.add_option(
"-d",
"--delself",
help="Set del self.",
type="int",
default=1
)
(options, _) = parse.parse_args()
print "Options: %s" % options
tc = TestClass(del_self=options.delself)
signal.signal(signal.SIGQUIT, tc.signal_handler)
while True:
pass
If I ran the script with:
python deltest.py --delself 1
And issue killall -3 python
I get:
Received signal. Now performing unusual cleanup.
Did unusual cleanup
Doing del self
Now performing usual cleanup.
Where as, if I do python deltest.py --delself 0
again followed by the kill signal, i get:
Received signal. Now performing unusual cleanup.
Did unusual cleanup
Doing self.__del__()
Now performing usual cleanup.
Now performing usual cleanup.
Why is the __del__
method executed twice in this case?
Thanks!
In object-oriented programming, A destructor is called when an object is deleted or destroyed. Destructor is used to perform the clean-up activity before destroying the object, such as closing database connections or filehandle. In Python we use __del__() method to perform clean-up task before deleting the object.
__del__ is a destructor method which is called as soon as all references of the object are deleted i.e when an object is garbage collected. Example: Here is the simple example of destructor. By using del keyword we deleted the all references of object 'obj', therefore destructor invoked automatically.
'self' is only a reference to the object. 'del self' is deleting the 'self' reference from the local namespace of the kill function, instead of the actual object.
self represents the instance of the class. By using the “self” we can access the attributes and methods of the class in python. It binds the attributes with the given arguments. The reason you need to use self. is because Python does not use the @ syntax to refer to instance attributes.
del self
does almost nothing -- it only deletes the local variable that is named self
. But as that isn't the last reference to the instance (whatever called this method also still has a reference, at least) the object will continue to exist.
Calling __del__
manually also achieves nothing except for running that method; it doesn't delete anything.
What does work is removing the last reference to an object: in this case, del tc
inside the main method would have remove that last reference, as far as I can see. Then the object would have been garbage collected, and then Python calls __del__
.
So that's why __del__
happens twice: one time when you call it manually as a normal function, and one time when the object is garbage collected when the program ends.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With