Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

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?

like image 406
Arlaharen Avatar asked Jul 10 '09 19:07

Arlaharen


People also ask

What is the use of __ del __ in Python?

__del__ is a destructor method which is called as soon as all references of the object are deleted i.e when an object is garbage collected. Example: Here is the simple example of destructor. By using del keyword we deleted the all references of object 'obj', therefore destructor invoked automatically.

Can you Del self in Python?

del self does almost nothing -- it only deletes the local variable that is named self . But as that isn't the last reference to the instance (whatever called this method also still has a reference, at least) the object will continue to exist.

How do you delete a class in Python?

To delete an object in Python, we use the 'del' keyword.


2 Answers

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.

like image 60
Lennart Regebro Avatar answered Oct 28 '22 14:10

Lennart Regebro


Not necessarily. You'll encounter problems when you have cyclic references. Eli Bendersky does a good job of explaining this in his blog post:

  • Safely using destructors in Python
like image 34
ars Avatar answered Oct 28 '22 16:10

ars