Java final vs Py __del__

Duncan Booth duncan at NOSPAMrcp.co.uk
Thu Nov 27 06:42:42 EST 2003


Kepes Krisztian <Kepes.Krisztian at peto.hu> wrote in 
news:mailman.1133.1069928021.702.python-list at python.org:

> In the Py the __del__ is same java's final, or it is to be called in
> every way by GC ?

There is more than one implementation of Python. In C Python, __del__ will 
be called as soon as there are no more references to the object, but the 
Java implementation of Python will never call __del__ until the object is 
garbage collected. 

Even in removing the last reference to an object, which causes __del__ to 
be called can happen in a slightly suprising way. Usually a variable going 
out of scope would be sufficient to release the object it referred to 
(assuming of course there are no other references to the same object), but 
if a function throws an exception, the objects referenced by the local 
variable will have their lifetimes extended, typically until the next time 
an exception is thrown (which probably happens in a completely unrelated 
function). The garbage collector can also cause objects to be released by 
collecting the objects which kept them alive, but if an object that 
participates directly in a cycle has a __del__ method then it will never be 
garbage collected, so its __del__ will never be called.

When Python exits, it does its best to ensure that all objects are released 
in an orderly manner, but sometimes that just isn't possible. So some 
objects may not get their __del__ methods called on program exit, and other 
objects may find that when __del__ is called, there are no other objects 
around for them to reference.

> 
> I build this method as safe method: if the programmer don't do any
> closing/freeing thing, I do that ?

No, this won't work reliably. If you want to do this, look at the atexit 
function.

> 
> simple example:
> 
> class a:
>       def __init__(self,filename):
>           self.__filename=filename
>           self.__data=[]
>           self.__file=None
>       def open(self):
>           self.__file=open(self.__filename,"w")
>       def write(self,data):
>           self.__data.append(data)
>       def close(self):
>           self.__file.writelines(self.__data)
>           self.__file.close()
>           self.__file=None
>       def __del__(self):
>           if self.__file<>None:
>              self.close()
>           # like destructor: we do the things are forgotten by
>           programmer
> 
> Thanx for infos:
> 

What I would suggest you do here, is something like (this is untested code, 
so it may have errors):

import weakref
import atexit

ObjectsToClose = weakref.WeakValueDictionary()

def CloseObjects():
    try:
        while true:
            key, o = ObjectsToClose.popitem()
            o.close()
    except:
        pass

atexit.register(CloseObjects)

class a:
      def __init__(self,filename):
          self.__filename=filename
          self.__data=[]
          self.__file=None
          ObjectsToClose[id(self)] = self
      ... rest of class a goes here ...

This code will ensure that the close method gets called on each of your 
objects when the program exits (unless you are running on Windows and the 
user uses control+break to kill the program --- if you are then you'll need 
some additional code to ensure that atexit gets called correctly).

The WeakValueDictionary will automatically remove from itself any objects 
which are destroyed before the program closes.

-- 
Duncan Booth                                             duncan at rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?




More information about the Python-list mailing list