Cyclic references et C libraries

F

Fabien SK

Hi,

I have a problem with a python module that uses C objects. In this
module (not mine, found on the net), I have one parent objet that
maintains a list of child objects. The child objects have a reference on
the parent object, so there is a cycle.
The parent object has a file handle (it is a native C object, not a
python "file object") as a member. This handle can be used with
functions like "lib_open", "lib_close", "lib_read_section".
My problem is that:
- I can not release the parent object in a fully automated manner, so
there is a leak, and since there is a native object, the handle will not
be closed. I can not modify the library to wrap the handle in a class,
because if such a class has a "__del__" method the python garbage
collector will not clean the cycle

I find it not funny to have leaks in Python, and to have to clean objet
by hand.

One solution would be to wrap the parent objet in a new class
(forwarding all the calls to the parent object). In the "__del__" method
of this class, I would clean the list of children object, and then
remove the reference on the parent objet so its "__del__" method will be
called. Am I right ?

Last question: why does the python file objects not have a "__del__"
method ? How the file can be closed when the last reference is remove ?
If I do a simple test, there is not file leak:

class Toto:
def __init__(self):
self.file = open("tata")

while 1:
a = Toto()
b = Toto()
a.member = b
b.member = a

The GC can clean the cycle because the file object doesn't have a
"__del__" method.

Fabien
 
M

Martin v. =?iso-8859-15?q?L=F6wis?=

Fabien SK said:
One solution would be to wrap the parent objet in a new class
(forwarding all the calls to the parent object). In the "__del__"
method of this class, I would clean the list of children object, and
then remove the reference on the parent objet so its "__del__" method
will be called. Am I right ?

I would not wrap the parent object, but the file handle. So do

class Handle:
def __init__(self, *args):
self.h = lib_open(*args)
def read_section(self, *args):
return lib_read_section(self.h, *args)
def __del__(self):
lib_close(self.h)

class Parent:
def __init__(self, ...):
# change
# self.handle = lib_open(...)
# to
self.Handle(...)

Then, the Handle class won't participate in a cycle, and it can safely
have an __del__.
Last question: why does the python file objects not have a "__del__"
method ? How the file can be closed when the last reference is remove
?

If a Python type is implemented in C, it does not need to have an
__del__. Instead, having a tp_del slot in its PyTypeObject C structure
is sufficient.

Regards,
Martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top