I see why a cycle that has multiple objects with a __del__ method is a problem.
Once you call __del__ on one of the objects, its no longer usable by the others, and its not clear which order is correct. My question regards the case where a cycle of objects only has 1 object which has a __del__. I think a correct strategy to collect the entire cycle is the same one used on a single object. On a single object Python uses: 1. Temporarily revive object 2. Call __del__ 3. Unrevive object (if(--refcount == 0) then we're done), otherwise it was resurrected). We can apply this to the whole cycle: 1. Temporarily revive entire cycle (each of its objects) 2. Call __del__ 3. Unrevive the objects of the entire cycle (each of its objects). Step 1 will allow __del__ to run safely. Since there is only one __del__ in the cycle, it is not dangerous that its references will disappear from "under its feet". (Some code restructuring will probably be necessary, because of assumptions that are hard-coded into slot_tp_del and subtype_dealloc). I believe this enhancement is important, because: A. When using existing code -- you do not control whether its objects have a __del__. In my experience, a majority of these cases only have a single __del__-containing object in their cycles. B. Python's exit cleanup calls __del__ in the wrong order, and Python's runtime is full of cycles (Each global is a cycle, including the class objects themselves: class->dict->function->func_globals)). These cycles very often have only 1 __del__ method. Some examples of the problem posed by B: http://www.google.com/search?q=ignored+%22%27NoneType%27+object+has+no+attribute%22+%22__del__+of%22&btnG=Search Ugly workarounds exist even in the standard library [subprocess]: "def __del__(self, sys=sys):"). 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]. 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 I believe applying the above enhancement would solve these problems. _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com