Del MyClass does not call .__ del __ () object

I have a class that opens a file for writing. In my destructor, I call a function that closes the file:

class MyClass: def __del__(self): self.close() def close(self): if self.__fileHandle__ is not None: self.__fileHandle__.close() 

but when I delete an object with code like:

 myobj = MyClass() myobj.open() del myobj 

If I try to restore an object, I get a value error:

 ValueError: The file 'filename' is already opened. Please close it before reopening in write mode. 

whereas if I call myobj.close() before del myobj , I do not get this problem. So why is the call to __del__() not called?

+6
source share
4 answers

Are you sure you want to use __del__ ? problems with __del__ and garbage collection.

Instead, you can make MyClass a context manager :

 class MyClass(object): def __enter__(self): return self def __exit__(self,ext_type,exc_value,traceback): if self.__fileHandle__ is not None: self.__fileHandle__.close() 

Thus, you can use MyClass as follows:

 with MyClass() as myobj: ... 

and myobj.__exit__ (and therefore self.__fileHandle__.close() ) will be called when Python leaves with-block .

+8
source

This is not what del does. It is __del__ that __del__ has the same name as del , because they are not related to each other. In modern terminology, the __del__ method will be called a finalizer, not a destructor, and the difference is important.

The small difference is that it is easy to guarantee when the call to the destructor is called, but you have very few guarantees as to when __del__ will be called, and it will never be called. This can lead to various circumstances.

If you want lexical coverage, use the with statement. Otherwise, call myobj.close() directly. The del operator only removes links, not objects.

I found another answer ( link ) to another question that answers this in more detail. Unfortunately, the accepted answer to this question contains flagrant errors.

Edit: As commenters noted, you need to inherit from object . That's fine, but it's still possible that __del__ will never be called (you might be lucky). See related answer above.

+8
source

Your code should inherit from object - at the same time it was not considered obsolete (except in special cases) for at least six years.

You can read __del__ here: http://docs.python.org/reference/datamodel.html#object. del

The short version of why you need to inherit from object is that __del__ is only "magic" in new-style classes.

If you need to rely on the call of the finalizer, I highly recommend using the context manager approach recommended in other answers, because it is a portable, reliable solution.

+2
source

Maybe something else refers to it, so __del__ not called (yet).

Consider this code:

 #!/usr/bin/env python import time class NiceClass(): def __init__(self, num): print "Make %i" % num self.num = num def __del__(self): print "Unmake %i" % self.num x = NiceClass(1) y = NiceClass(2) z = NiceClass(3) lst = [x, y, z] time.sleep(1) del x del y del z time.sleep(1) print "Deleting the list." del lst time.sleep(1) 

It does not call __del__ instances of NiceClass until we remove the list that references them.

Unlike C ++, __del__ not called unconditionally to destroy an object on demand. GC makes things a little more complicated. Here is some info: http://arctrix.com/nas/python/gc/

0
source

Source: https://habr.com/ru/post/906284/


All Articles