How To Ensure The __del__ Function Is Called On A Python Class As Is Commonly (but Incorrectly) Expected?
Solution 1:
If you understand all that, why not do it in the Pythonic way? Compare another class where cleanup is important: tempfile.TemporaryDirectory
.
withTemporaryDirectory() as tmp:
# ...
# tmp is deleted
def foo():
tmp = TemporaryDirectory()
foo()
# tmp is deleted
How do they do this? Here's the relevant bit:
import weakref
classFoo():
def__init__(self, name):
self.name = name
self._finalizer = weakref.finalize(self, self._cleanup, self.name)
print("%s reporting for duty!" % name)
@classmethoddef_cleanup(cls, name):
print("%s feels forgotten! Bye!" % name)
defcleanup(self):
if self._finalizer.detach():
print("%s told to go away! Bye!" % self.name)
deffoo():
print("Calling Arnold")
tmpfoo = Foo("Arnold")
print("Finishing with Arnold")
foo()
# => Calling Arnold# => Arnold reporting for duty# => Finishing with Arnold# => Arnold feels forgotten. Bye!defbar():
print("Calling Rocky")
tmpbar = Foo("Rocky")
tmpbar.cleanup()
print("Finishing with Rocky")
bar()
# => Calling Rocky# => Rocky reporting for duty!# => Rocky told to go away! Bye!# => Finishing with Rocky
weakref.finalize
will trigger _cleanup
when the object is garbage-collected, or at the end of the program if it's still around. We can keep the finaliser around so that we can explicitly kill the object (using detach
) and mark it as dead so the finaliser is not called (when we want to manually handle the cleanup).
If you want to support the context usage with with
, it is trivial to add __enter__
and __exit__
methods, just invoke cleanup
in __exit__
("manual cleanup" as discussed above).
Solution 2:
This is a pattern I have been employing that achieves this using the atexit python module.
class Demo(object):
def __init__(self, *args, **kwargs):
import atexit
atexit.register(self.__del__)
def __del__(self):
print("__del__ being called!")
t1 = Demo()
t2 = Demo()
quit()
When pasted into a python command prompt, this is the total output:
Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>>>>classDemo(object):...def__init__(self, *args, **kwargs):...import atexit... atexit.register(self.__del__)......def__del__(self):...print("__del__ being called!")...>>>t1 = Demo()>>>t2 = Demo()>>>>>>quit()
__del__ being called!
__del__ being called!
Post a Comment for "How To Ensure The __del__ Function Is Called On A Python Class As Is Commonly (but Incorrectly) Expected?"