Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
My Python class defines __del__ but it is not called when I delete the object
The __del__ is a magic method in Python that serves as a destructor. Magic methods (also called Dunder methods) are identified by double underscores (__) as prefix and suffix.
In Python, we create an object using __new__() and initialize using __init__(). However, to destruct an object, we have __del__(). Sometimes __del__() may not be called when you expect it to be.
Basic Example
Let us create and delete an object ?
class Demo:
def __init__(self):
print("We are creating an object.")
# destructor
def __del__(self):
print("We are deleting an object.")
# Creating and deleting an object
ob = Demo()
del ob
We are creating an object. We are deleting an object.
Why __del__ May Not Be Called
However, there are several reasons why a class defines __del__ but it's not called when the object is deleted ?
Reference Count Issue
The del statement does not necessarily call __del__(). It simply decrements the object's reference count, and only if this reaches zero is __del__() called ?
class Demo:
def __init__(self, name):
self.name = name
print(f"Creating {self.name}")
def __del__(self):
print(f"Deleting {self.name}")
# Multiple references to the same object
obj = Demo("Object1")
ref1 = obj # Second reference
ref2 = obj # Third reference
del obj # __del__ not called yet (2 references remain)
del ref1 # __del__ not called yet (1 reference remains)
del ref2 # Now __del__ is called (0 references)
Creating Object1 Deleting Object1
Circular References
If your data structures contain circular links, the reference counts will never go back to zero. Python's garbage collector may run sometime after the last reference vanishes ?
class Node:
def __init__(self, name):
self.name = name
self.ref = None
print(f"Creating {self.name}")
def __del__(self):
print(f"Deleting {self.name}")
# Creating circular reference
node1 = Node("Node1")
node2 = Node("Node2")
node1.ref = node2 # node1 references node2
node2.ref = node1 # node2 references node1 (circular!)
del node1
del node2
# __del__ may not be called immediately due to circular reference
print("End of program")
Creating Node1 Creating Node2 End of program
Solutions to Fix the Issue
Use Explicit Cleanup Methods
Do not rely on __del__() directly. Create a close() method that can be called multiple times safely ?
class FileHandler:
def __init__(self, filename):
self.filename = filename
self.closed = False
print(f"Opening {filename}")
def close(self):
if not self.closed:
print(f"Closing {self.filename}")
self.closed = True
def __del__(self):
self.close() # Safe to call multiple times
# Proper usage
handler = FileHandler("data.txt")
handler.close() # Explicit cleanup
del handler
Opening data.txt Closing data.txt
Avoid Circular References
Use the weakref module to avoid cyclical references. It allows you to point to objects without incrementing their reference count ?
import weakref
class Node:
def __init__(self, name):
self.name = name
self._ref = None # Will hold weakref
print(f"Creating {self.name}")
def set_ref(self, other):
self._ref = weakref.ref(other) # Weak reference
def get_ref(self):
return self._ref() if self._ref else None
def __del__(self):
print(f"Deleting {self.name}")
# No circular reference issue
node1 = Node("Node1")
node2 = Node("Node2")
node1.set_ref(node2) # Weak reference, no circular dependency
del node1
del node2
print("Cleanup complete")
Creating Node1 Creating Node2 Deleting Node1 Deleting Node2 Cleanup complete
Best Practices
| Issue | Solution | Best Practice |
|---|---|---|
| Multiple references | Explicit cleanup | Use close() method |
| Circular references | Weak references | Use weakref module |
| Resource management | Context managers | Use with statement |
Conclusion
__del__() may not be called immediately due to reference counting or circular references. Use explicit cleanup methods and weak references to ensure proper resource management. Consider context managers with with statements for automatic cleanup.
