[Python-Dev] Cycle collection enhancement idea

eyal.lotem+pyutils@gmail.com eyal.lotem at gmail.com
Sun Jun 29 13:30:09 CEST 2008


On Jun 28, 6:32 pm, "Martin v. Löwis" <mar... at v.loewis.de> wrote:
> > Example:
>
> > import os
> > class RunningFile(object):
> >     filename = '/tmp/running'
> >     def __init__(self):
> >         open(self.filename, 'wb')
> >     def __del__(self):
> >         os.unlink(self.filename)
> > running_file = RunningFile()
>
> > The deller object is in a cycle as described above [as well as the
> > Deller class itself].
>
> I think you are mistaken here. The RunningFile instance in above code
> is *not* part of a cycle. It doesn't have any instance variables (i.e.
> its __dict__ is empty), and it only refers to its class, which (AFAICT)
> doesn't refer back to the instance.

As I explained above, it *is* part of a cycle: """including
the class objects themselves: class->dict->function->func_globals""".

Note:
running_file.__class.__.__dict__['__init__'].func_globals['running_file']
is running_file.


>
> > When Python exits, it could call
> > deller.__del__() and then collect the cycle. But Python does the wrong
> > thing here, and gets rid of the globals before calling __del__:
> > Exception exceptions.AttributeError: "'NoneType' object has no
> > attribute 'unlink'" in <bound method RunningFile.__del__ of
> > <__main__.RunningFile object at 0x7f9655eb92d0>> ignored
>
> This is a different issue. For shutdown, Python doesn't rely on
> cyclic garbage collection (only). Instead, all modules get forcefully
> cleared, causing this problem.

I know. I assumed Python does not rely on cyclic garbage collectioin
for shutdown, because it wouldn't work, as _all_ globals that have
*any* instance method will be part of a cycle, and any of them which
have a __del__ will not be collected.

> > I believe applying the above enhancement would solve these problems.
>
> No, they wouldn't.
>
> To work around the real problem in your case, put everything that the
> destructor uses into an instance or class attribute:
>
> class RunningFile(object):
>     filename = '/tmp/running'
>     _unlink = os.unlink
>     def __init__(self):
>         open(self.filename, 'wb')
>     def __del__(self):
>         self._unlink(self.filename)
I *mentioned* this workaround. What I propose is not a workaround but
a solution. You wouldn't need to clean up module globals ad-hoc'ishly,
because the cyclic collection would collect your object, even with its
__del__.

> Regards,
> Martin
Please read my entire mail before replying to it. Thanks!
Eyal

> _______________________________________________
> Python-Dev mailing list
> Python-... at python.orghttp://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:http://mail.python.org/mailman/options/python-dev/python-dev2-garchiv...


More information about the Python-Dev mailing list