[Python-3000] PEP: Eliminate __del__

Raymond Hettinger python at rcn.com
Tue May 1 09:31:21 CEST 2007


PEP:  Eliminating __del__

Motivation

Historically, __del__ has been one of the more error-laden dark corners
of the language.  From an implementation point of view, it has
proven to be a thorny maintenance problem that grew almost beyond
the range of human comprehension once garbage collection was introduced.

>From a user point-of-view, the method is deceptively simple and tends
to lead to fragile designs.  The fragility arises in-part because it
is difficult to know when or if an object is going to be deleted whether
by reference counts going to zero or by garbage collection.  Even if all
the relationships are known at the time a script is written, a subsequent
maintainer may innocently introduce (directly or indirectly) a reference
that prevents the desired finalization code from running.  From a design
perspective, it is almost always better to provide for explicit finalization
(for example, experienced Python programmers have learned to call file.close()
 and connection.close() rather than rely on automatic closing when the
 file or sql connection goes out of scope).  For finalization that needs
to occur only a the end of all operations, users have learned to use atexit()
as the preferred technique.

That leaves a handful of cases where some action does need to be taken
when an object is being collected.  In those cases, users have turned
to __del__ "because it was there".  Through the school of hard-knocks,
they eventually learn to avoid to hazards of accidentally bringing the
object back to life during finalization and possibly leaving the object
in an invalid half-finalized state.  The risks occur because the object
is still alive at the time the arbitrary python code in __del__ is called.

The alternative is to code the automatic finalization steps using
weakref callbacks.  For those used to using __del__, it takes a little
while to learn the idiom but essentially the technique is hold a proxy
or ref with a callback to a boundmethod for finalization:
    self.resource = resource = CreateResource()
    self.callbacks.append(proxy(resource, resource.closedown))
In this manner, all of the object's resources can be freed automatically
when the object is collected.  Note, that the callbacks only bind
the resource object and not client object, so the client object
can already have been collected and the teardown code can be run
without risk of resurrecting the client (with a possibly invalid state).


Proposal

The proposal is to eliminate __del__ and thereby eliminate a strong
temptation to code implicit rather than explicit finalization.  The
remaining approaches to teardown procedures such as atexit() and
weakref callbacks are much less problematic and should become the
one way to do it.


More information about the Python-3000 mailing list