[Python-ideas] CPython's cyclic garbage collector (was Automatic context managers)
MRAB
python at mrabarnett.plus.com
Fri Apr 26 22:15:16 CEST 2013
On 26/04/2013 20:31, Dave Angel wrote:
> On 04/26/2013 01:57 PM, Chris Angelico wrote:
>> On Sat, Apr 27, 2013 at 3:42 AM, Dave Angel <davea at davea.name> wrote:
>>> I don't see what your "special" temporary object actually accomplishes.
>>> Seems to me you need to declare that your __del__() methods promise not to
>>> reference each other, and the gc would then check all objects in the cycle,
>>> and do its present behavior if any of the destructors is not specially
>>> declared.
>>
>> It wouldn't be declared; it'd simply throw an exception if anything
>> different happened.
>>
>>> I'm not sure how often you'd have a non-trivial destructor that wouldn't
>>> reference any objects. And doing a static analysis of what will happen
>>> during the destructor would be pretty messy. So the best I and come up with
>>> is to keep the declaration, but require a try/catch to cleanly terminate
>>> each destructor if it ever references anything in the tree.
>>
>> And yeah. If you catch the exception inside __del__, you can cope with
>> the destructed object yourself (or LBLY, if you wish). Alternatively,
>> you just proceed as normal, and when your __del__ throws an exception,
>> the gc then copes (not sure *how* it should cope - log it to stderr
>> and carry on?). Same as normal exception handling.
>>
>> The advantage of this style is that the code to deal with the cycle is
>> kept right in the cyclic object's destructor - right where the problem
>> is. Doing it through gc.garbage requires that some other operation
>> periodically check for garbage - after the GC has done its own
>> periodic check. Seems simpler/cleaner to do it as part of the gc run
>> itself.
>>
>
> You must think me dense by now. But I don't understand what the two
> different garbage collection operations are that you're positing.
>
> As far as I know, there's ref counting, which is quick, and frees
> something as soon as the count goes to zero. Then there's gc, which has
> to scan through all the objects from a known starting set, and identify
> those things which aren't accessible, and free any that don't have a
> __del__() method.
>
> And it's only in the gc step that cycles and such are identifiable.
>
Currently, if the GC finds a cycle and the objects in that cycle have
__del__ methods, the objects are not collected.
The suggestion is that in such a case the GC could call the __del__
method and then replace the object with a special "deleted" object,
removing any references to other objects and thus breaking the cycle.
If a __del__ method in one of the other objects subsequently tries to
use the deleted object, an exception would be raised (a kind of
AttributeError perhaps).
More information about the Python-ideas
mailing list