What is the best approach to implement the opposite of __init__ so that users can type del obj and expect that the deleted object is cleaned up properly?
Example:
import weakref
registry = weakref.WeakValueDictionary()
class myClass(object):
def __init__(self) -> None: # CREATOR
registry[id(self)] = self
def __destroy__(self): # DESTROYER
del registry[id(self)]
To make the case very explicit: My users expect that del obj results in a clean database that sits on disk. I merely use registry as a mock example hereof.
Test case:
a = myClass()
assert a in registry
del a # must trigger call to __destroy__
assert a not in registry
test case 2:
a = MyClass()
b = a
del a
assert b in registry
del b
assert len(registry) == 0
This problem is very well documented in [1, 2, 3, 4], but there does not seem to be any solution:
-
__del__does not guarantee any action until garbage collection, and that wont happen immediately. -
atexit.registeris too late, as I want the program to react todel obj -
I lack creativity to make a
context managers__enter__&__exit__work as the objects may have overlapping lifecycles (test case 2). -
Monking patching
delis not possible asdelis a reserved keyword. If anatexit-type register existed I would be able to attach__terminate__to thedelkeywork:
import keywords
keywords.register(del, myClass.__terminate__)
such that the behaviour would be:
def del(*args):
for arg in args:
if isinstance(arg, myClass):
arg.terminate()
keywords.del arg # let gc deal with the clean up
- The problem is not associated with cyclic references [4], but rather that
asserts are executed straight afterdeland that is too early for garbage collection.
[1] Python Gotchas 1: __del__ is not the opposite of __init__
[2] destructor - How do I correctly clean up a Python object? - Stack Overflow
[3] python - Opposite of __init__ in thread class? - Stack Overflow
[4] Safely using destructors in Python - Eli Bendersky's website