Предотвращение memory leaks на Python
Разбирая код на питоне, в очередной раз столкнулся со сложностями, которые возникают при анализе memory leaks. В данном случае это решилось разрезанием ссылок через установку None в одном из полей объекта в коллекции.
Cублимированный код без лишних деталей:
from typing import List
class Something(object):
def __init__(self) -> None:
super().__init__()
self.something_new = None
class SomethingNew(object):
def __init__(self, i: int = 0, something: Something = None) -> None:
super().__init__()
self.i = i
self.something = something
def add_something(collection: List[Something], i: int):
something = Something()
something.something_new = SomethingNew(i, something)
collection.append(something)
def check_memory(collection: List[Something]):
# for e in collection:
# e.something_new.something = None
collection.clear()
def main():
collection = list()
for i in range(1, 1024 * 128):
add_something(collection, i)
check_memory(collection)
if __name__ == '__main__': main()
Если включить ручное вырезание ссылок (убрать комментарии), то все будет работать как часы, память освободиться мгновенно. Проверить можно использовав библиотеку https://pypi.org/project/memory-profiler/ и добавив аннотацию @profile перед функцией main.
Вопрос в практике. Есть ли у вас устоявшаяся практика, как избегать ручного очищения циклических ссылок? Буду признателен за любой совет. Спасибо!