Is it really OK to do object closeing/disposing in __del__?

python

Solution

Short answer : No.

Long answer: Using `__del__` is tricky, mainly because it's not guaranteed to be called. That means you can't do things there that absolutely has to be done. This in turn means that `__del__` basically only can be used for cleanups that would happen sooner or later anyway, like cleaning up resources that would be cleaned up when the process exits, so it doesn't matter if `__del__` doesn't get called. Of course, these are also generally the same things Python will do for you. So that kinda makes `__del__` useless.

Also, `__del__` gets called when Python garbage collects, and you didn't want to wait for Pythons garbage collecting, which means you can't use `__del__` anyway.

So, don't use `__del__`. Use `__enter__/__exit__` instead.

FYI: Here is an example of a non-circular situation where the destructor did not get called:

class A(object):
    def __init__(self):
        print('Constructing A')

    def __del__(self):
        print('Destructing A')

class B(object):
    a = A()

OK, so it's a class attribute. Evidently that's a special case. But it just goes to show that making sure `__del__` gets called isn't straightforward. I'm pretty sure I've seen more non-circular situations where `__del__` isn't called.

Problem

I have been thinking about how I write classes in Python. More specifically how the constructor is implemented and how the object should be destroyed. I don't want to rely on CPython's reference counting to do object cleanup. This basically tells me I should use with statements to manage my object life times and that I need an explicit close/dispose method (this method could be called from `__exit__` if the object is also a context manager). ``` class Foo(object): def __init__(self): pass def close(self): pass ``` Now, if all my objects behave in this way and all my code uses with statements or explicit calls to `close()` (or `dispose()`) I don't realy see the need for me to put any code in `__del__`. Should we really use `__del__` to dispose of our objects?

Original source