Предотвращение 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.

Вопрос в практике. Есть ли у вас устоявшаяся практика, как избегать ручного очищения циклических ссылок? Буду признателен за любой совет. Спасибо!


Ответы (0 шт):