En Wed, 07 Apr 2010 19:08:14 -0300, Brendan Miller <catph...@catphive.net>
escribió:
I'm used to C++ where destrcutors get called in reverse order of
construction
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()
try:
bar = Bar()
try:
# do something
finally:
bar.release_resources()
finally:
foo.release_resources()
I'm writing a ctypes wrapper for some native code, and I need to manage
some
memory. I'm wrapping the memory in a python class that deletes the
underlying
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):
delete_my_resource(self.res)
o = MyClass()
What happens is that as the program shuts down, delete_my_resource is
released
*before* o is released. So when __del__ get called, delete_my_resource
is now
None.
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. [1]
If you still want to implement __del__, keep a reference to
delete_my_resource in the method itself:
def __del__(self,
delete_my_resource=delete_my_resource):
delete_my_resource(self.res)
(and do the same with any global name that delete_my_resource itself may
reference).
The best approach is to store a weak reference to foo and bar somewhere;
weak references are notified right before the referent is destroyed. [4]
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
counts
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 [2] and in _PyModule_Clear in
moduleobject.c [3]
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
behavior.
[1] http://docs.python.org/reference/datamodel.html#object.__del__
[2] http://svn.python.org/view/python/trunk/Python/import.c?view=markup
[3]
http://svn.python.org/view/python/trunk/Objects/moduleobject.c?view=markup
[4] http://docs.python.org/library/weakref.html
--
Gabriel Genellina
--
http://mail.python.org/mailman/listinfo/python-list