Сборка мусора Python - PullRequest
       9

Сборка мусора Python

37 голосов
/ 24 июня 2009

Я создал некоторый код Python, который создает объект в цикле, и на каждой итерации перезаписывает этот объект новым объектом того же типа. Это делается 10.000 раз, и Python занимает 7 МБ памяти каждую секунду, пока не будет использована моя 3 ГБ ОЗУ. Кто-нибудь знает способ удаления объектов из памяти?

Ответы [ 7 ]

25 голосов
/ 31 октября 2010

Я думаю, что это круговая ссылка (хотя вопрос об этой информации не явный).

Один из способов решения этой проблемы - вызвать сборку мусора вручную. Когда вы вручную запускаете сборщик мусора, он также будет очищать объекты с круглыми ссылками.

import gc

for i in xrange(10000):
    j = myObj()
    processObj(j)
    #assuming count reference is not zero but still
    #object won't remain usable after the iteration

    if !(i%100):
        gc.collect()

Здесь не запускайте сборщик мусора слишком часто, потому что он имеет свои служебные данные, например если вы будете запускать сборщик мусора в каждом цикле, интерпретация станет чрезвычайно медленной.

20 голосов
/ 24 июня 2009

Вы не предоставили достаточно информации - это зависит от специфики создаваемого вами объекта и от того, что еще вы делаете с ним в цикле. Если объект не создает циклические ссылки, он должен быть освобожден на следующей итерации. Например, код

for x in range(100000):
  obj = " " * 10000000

не приведет к постоянно увеличивающемуся выделению памяти.

13 голосов
/ 24 июня 2009

Это старая ошибка, которая была исправлена ​​для некоторых типов в Python 2.5. То, что происходило, было то, что python не был так хорош в сборе таких вещей, как пустые списки / словари / tupes / floats / ints. В Python 2.5 это было исправлено ... в основном. Однако плавающие и целые числа являются синглетонами для сравнения, поэтому после создания одного из них он остается в течение всего времени, пока переводчик жив. Меня укусило это худшее, когда я имел дело с большим количеством поплавков, так как они имеют неприятную привычку быть уникальными. Это было охарактеризовано для Python 2.4 и обновлено о том, что оно складывается в python 2.5

Лучший способ, который я нашел, - это обновить до python 2.5 или новее, чтобы решить проблему списков / словарей / кортежей. Для чисел единственное решение состоит в том, чтобы не допустить попадания большого количества чисел в питон. Я сделал это с помощью своей собственной оболочки для объекта c ++, но у меня сложилось впечатление, что numpy.array даст аналогичные результаты.

Как пост-скрипт, я понятия не имею, что случилось с этим в Python 3, но я подозреваю, что числа по-прежнему являются частью единого числа. Так что утечка памяти на самом деле является особенностью языка.

6 голосов
/ 24 июня 2009

Если вы создаете циклические ссылки, ваши объекты не будут немедленно освобождены, а должны ждать запуска цикла GC.

Вы можете использовать модуль weakref для решения этой проблемы или явно удалить ваши объекты после использования.

3 голосов
/ 10 января 2010

Я обнаружил, что в моем случае (с Python 2.5.1) с циклическими ссылками, включающими классы с методами __del__(), не только сборка мусора не происходила своевременно, но и методы __del__() моих объектов никогда не вызывается, даже когда скрипт завершается. Поэтому я использовал weakref , чтобы разорвать циклические ссылки, и все было хорошо.

Благодарность Майлзу, который предоставил мне всю информацию в своих комментариях, чтобы я соединил это.

1 голос
/ 24 июня 2009

Вот одна вещь, которую вы можете сделать в REPL, чтобы вызвать разыменование переменной:

>>> x = 5
>>> x
5
>>> del x
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
0 голосов
/ 08 мая 2018

weakref может использоваться для кругового структурированного кода объекта, как в объясненном примере

...