Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the use of the __del__() method in Python?

From Python documentation:

It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits.

As far as I understand, there is also no way to guarantee an object stops existing before the interpreter exits, since it's up to the garbage collector to decide if and when an object is deleted.

So what's the point of having this method at all? You can write cleanup code inside it, but there's no guarantee it will ever be executed.

I know you can solve this using try-finally or with clauses, but I still wonder what would be a meaningful use case of the __del__() method.

like image 722
PieterNuyts Avatar asked Feb 28 '20 09:02

PieterNuyts


People also ask

What is the purpose of __ Str__ method in Python?

Python __str__() This method returns the string representation of the object. This method is called when print() or str() function is invoked on an object. This method must return the String object.

What is the main purpose of the _ _init_ _ method?

The __init__ method lets the class initialize the object's attributes and serves no other purpose. It is only used within classes.

What is __ method in Python?

The __call__ method enables Python programmers to write classes where the instances behave like functions. Both functions and the instances of such classes are called callables.

What is __ eq __ method in Python?

Summary. Implement the Python __eq__ method to define the equality logic for comparing two objects using the equal operator ( == )


2 Answers

After reading all of these answers—none of which satisfactorily answered all of my questions/doubts—and rereading Python documentation, I've come to a conclusion of my own. This the summary of my thoughts on the matter.


Implementation-agnostic

The passage you quoted from the __del__ method documentation says:

It is not guaranteed that the __del__() methods are called for objects that still exist when the interpreter exits.

But not only is it not guaranteed that __del__() is called for objects being destroyed during interpreter exit, it is not even guaranteed that objects are garbage collected at all, even during normal execution—from the "Data model" section of the Python Language Reference:

Objects are never explicitly destroyed; however, when they become unreachable they may be garbage-collected. An implementation is allowed to postpone garbage collection or omit it altogether — it is a matter of implementation quality how garbage collection is implemented, as long as no objects are collected that are still reachable.

Thus, replying to your question:

So what's the point of having this method at all? You can write cleanup code inside it, but there's no guarantee it will ever be executed.

From an implementation-agnostic perspective, are there any uses for the __del__ method, as a fundamental component of one's code that can be relied on? No. None at all. It is essentially useless from this perspective.

From a practical point of view, though, as other answers have pointed out, you can use __del__ as a last-resort mechanism to (try to) ensure that any necessary cleanup is performed before the object is destroyed, e.g. releasing resources, if the user forgot to explicitly call a close method. This is not so much a fail-safe as it is a "it doesn't hurt to add an extra safety mechanism even if it's not guaranteed to work"—and in fact, most Python implementations will catch that most of the time. But it's nothing to be relied on.


Implementation-specific

That being said, if you know that your program will run on a specific set of Python implementations, then you can rely on the implementation details of garbage collection—for instance, if you use CPython, you can "rely on" the fact that, during normal execution (i.e. outside of interpreter exit), if the reference count of a non-cyclically-referenced object reaches zero, it will be garbage collected and its __del__ method will be called, as other answers have pointed out. From the same subsection as above:

CPython implementation detail: CPython currently uses a reference-counting scheme with (optional) delayed detection of cyclically linked garbage, which collects most objects as soon as they become unreachable, but is not guaranteed to collect garbage containing circular references.

But still, this is really precarious and something to not be really relied on, since as mentioned it is only guaranteed for objects that are not part of a cyclic reference graph. Also:

Other implementations act differently and CPython may change. Do not depend on immediate finalization of objects when they become unreachable (so you should always close files explicitly).


Bottom line

From a purist point of view, the __del__ method is completely useless. From a slightly less purist point of view, it is still almost useless. From a practical point of view, it might be useful as a complementary—but never essential—feature of your code.

like image 108
Anakhand Avatar answered Oct 02 '22 19:10

Anakhand


It can be used to dispose of resources managed by the object : https://github.com/python/cpython/blob/master/Lib/zipfile.py#L1805

As noted in the docstring, this is a kind of last resort as the object with be closed only when gc is running.

As you said in your question, the prefered way is to call close yourself, either by calling .close() directly or using a context manager with Zipfile() as z:

like image 27
Cyril Jouve Avatar answered Oct 02 '22 20:10

Cyril Jouve