On 7 tammi, 16:06, Andrey Antukh <[email protected]> wrote: > I've been experimenting, and I found a strange behavior. In the View class > if I define the __ del__ method, and is never executed. In instances of > other classes, which are members of View, feel the same behavior (eg > HttpRequest is not removed by a garbage collector). > > The fault lies primarily in this line (django/views/generic/base.py): > > def view(request, *args, **kwargs): > # [...] > * if hasattr(self, 'get') and not hasattr(self, 'head'): > self.head = self.get* > # [...] > > When you create alias methods once the class has been instantiated seems to > make some references (cyclical?) which prevent the garbage collector remove > them. > > I have reproduced the same behavior with simple classes to verify the > problem:https://gist.github.com/4475138 > If a custom view defines a head method, the problem disappears. > > So, is how it should work? I'm wrong about something? > > Thank you very much.
The reason is that if you define a __del__ method for a class, and an instance of that class is part of a reference cycle, then Python will not release any object which is reachable from the cycle. This is ugly, and once you know this you know to avoid __del__ methods if possible. More here: http://docs.python.org/2/library/gc.html#gc.garbage You can try to have a special cleaner object - the idea is that on __init__ of an in-cycle object you assign a cleaner object to self. Pass the cleaner object the data you want to clean up. The data passed must not be part of the cycle or the trick doesn't work. When the in- cycle object is garbage collected, then the cleaner object will be garbage collected too (only reference to it is from the in-cycle object). Now, the __del__ of the cleaner object is called and you can do cleanup there (again, assuming that the cleaner is not part of a cycle). This is ugly but if you have a cyclic object and you need to have __del__ I don't know of anything better (ideas welcome!). This idea is implemented here: https://github.com/akaariai/django_pooled/blob/master/base.py#L134 - the idea is that when a ConnectionWrapper is created we also create PoolReleaser. The PoolReleaser has the needed data to release a connection to the pool. When the ConnectionWrapper is gc'd, the PoolReleaser's __del__ is called and we can release the connection back to pool. Avoid __del__ if possible, - Anssi -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
