Вы пробовали gc.set_debug () ?
Вам нужно задать себе простые вопросы:
- Использую ли я объекты с
__del__
методами? Нужны ли они мне абсолютно однозначно?
- Могу ли я получить справочные циклы в моем коде? Разве мы не можем разбить эти круги, прежде чем избавиться от объектов?
Видите ли, основной проблемой будет цикл объектов, содержащих __del__
методы:
import gc
class A(object):
def __del__(self):
print 'a deleted'
if hasattr(self, 'b'):
delattr(self, 'b')
class B(object):
def __init__(self, a):
self.a = a
def __del__(self):
print 'b deleted'
del self.a
def createcycle():
a = A()
b = B(a)
a.b = b
return a, b
gc.set_debug(gc.DEBUG_LEAK)
a, b = createcycle()
# remove references
del a, b
# prints:
## gc: uncollectable <A 0x...>
## gc: uncollectable <B 0x...>
## gc: uncollectable <dict 0x...>
## gc: uncollectable <dict 0x...>
gc.collect()
# to solve this we break explicitely the cycles:
a, b = createcycle()
del a.b
del a, b
# objects are removed correctly:
## a deleted
## b deleted
gc.collect()
Я бы действительно рекомендовал вам отмечать объекты / концепции, которые циклически повторяются в вашем приложении, и фокусироваться на их времени жизни: когда они вам больше не нужны, есть ли у нас что-либо, ссылающееся на это?
Даже для циклов без __del__
методов у нас может возникнуть проблема:
import gc
# class without destructor
class A(object): pass
def createcycle():
# a -> b -> c
# ^ |
# ^<--<--<--|
a = A()
b = A()
a.next = b
c = A()
b.next = c
c.next = a
return a, b, b
gc.set_debug(gc.DEBUG_LEAK)
a, b, c = createcycle()
# since we have no __del__ methods, gc is able to collect the cycle:
del a, b, c
# no panic message, everything is collectable:
##gc: collectable <A 0x...>
##gc: collectable <A 0x...>
##gc: collectable <dict 0x...>
##gc: collectable <A 0x...>
##gc: collectable <dict 0x...>
##gc: collectable <dict 0x...>
gc.collect()
a, b, c = createcycle()
# but as long as we keep an exterior ref to the cycle...:
seen = dict()
seen[a] = True
# delete the cycle
del a, b, c
# nothing is collected
gc.collect()
Если вам необходимо использовать словари или историю, похожие на «видимые», будьте осторожны, сохраняя только те данные, которые вам нужны, и не обращаясь к ним со стороны.
Я немного разочарован сейчас set_debug
, я бы хотел, чтобы его можно было настроить для вывода данных куда-то, кроме stderr, но, надеюсь, , который скоро должен измениться .