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 deletedHow 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 Rockyweakref.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?"