order that destructors get called?
gagsl-py2 at yahoo.com.ar
Thu Apr 8 07:03:19 CEST 2010
En Wed, 07 Apr 2010 19:08:14 -0300, Brendan Miller <catphive at catphive.net>
> I'm used to C++ where destrcutors get called in reverse order of
> like this:
> Foo foo;
> Bar bar;
> // calls Bar::~Bar()
> // calls Foo::~Foo()
That behavior is explicitly guaranteed by the C++ language. Python does
not have such guarantees -- destructors may be delayed an arbitrary amount
of time, or even not called at all.
In contrast, Python does have a `try/finally` construct, and the `with`
statement. If Foo and Bar implement adequate __enter__ and __exit__
methods, the above code would become:
with Foo() as foo:
with Bar() as bar:
# do something
On older Python versions it is more verbose:
foo = Foo()
bar = Bar()
# do something
> I'm writing a ctypes wrapper for some native code, and I need to manage
> memory. I'm wrapping the memory in a python class that deletes the
> memory when the python class's reference count hits zero.
If the Python object lifetime is tied to certain lexical scope (like the
foo,bar local variables in your C++ example) you may use `with` or
`finally` as above.
If some other object with a longer lifetime keeps a reference, see below.
> When doing this, I noticed some odd behaviour. I had code like this:
> def delete_my_resource(res):
> # deletes res
> class MyClass(object):
> def __del__(self):
> o = MyClass()
> What happens is that as the program shuts down, delete_my_resource is
> *before* o is released. So when __del__ get called, delete_my_resource
> is now
Implementing __del__ is not always a good idea; among other things, the
garbage collector cannot break a cycle if any involved object contains a
__del__ method. 
If you still want to implement __del__, keep a reference to
delete_my_resource in the method itself:
(and do the same with any global name that delete_my_resource itself may
The best approach is to store a weak reference to foo and bar somewhere;
weak references are notified right before the referent is destroyed. 
And last, if you want to release something when the program terminates,
you may use the atexit module.
> What I'm wondering is if there's any documented order that reference
> get decremented when a module is released or when a program terminates.
Not much, as Stephen Hansen already told you; but see the comments in
PyImport_Cleanup function in import.c  and in _PyModule_Clear in
Standard disclaimer: these undocumented details only apply to the current
version of CPython, may change in future releases, and are not applicable
at all to other implementations. So it's not a good idea to rely on this
More information about the Python-list