Найти все ссылки на объект в python
Что такое хороший способ найти все ссылки на объект в Python?
Причина, по которой я спрашиваю, заключается в том, что, похоже, у нас "утечка памяти". Мы загружаем файлы изображений на сервер из веб-браузера. Каждый раз, когда мы делаем это, использование памяти на сервере увеличивается пропорционально размеру только что загруженного файла. Эта память никогда не освобождается сборщиком мусора в Python, поэтому я думаю, что, возможно, существуют случайные ссылки, указывающие на данные изображения, которые не удаляются или выходят из области действия даже в конце каждого запроса.
Я полагаю, было бы неплохо иметь возможность спросить python: "Какие ссылки все еще указывают на эту память?" так что я могу понять, что мешает сборщику мусора освободить его.
В настоящее время мы запускаем Python и Django на сервере Heroku.
Ответы
Ответ 1
Стандартная библиотека Python имеет модуль gc
, содержащий API сборщика мусора. Одна из функций, которую вы хотите получить, -
gc.get_objects()
Эта функция возвращает список всех объектов, которые в настоящее время отслеживаются сборщиком мусора. Следующий шаг - проанализировать его.
Если вы знаете объект, который хотите отслеживать, вы можете использовать функцию sys
module getrefcount
:
>>> x = object()
>>> sys.getrefcount(x)
2
>>> y = x
>>> sys.getrefcount(x)
3
Ответ 2
Модуль Python gc
имеет несколько полезных функций, но это звучит как gc.get_referrers()
- это то, что вы ищете. Вот пример:
import gc
def foo():
a = [2, 4, 6]
b = [1, 4, 7]
l = [a, b]
d = dict(a=a)
return l, d
l, d = foo()
r1 = gc.get_referrers(l[0])
r2 = gc.get_referrers(l[1])
print r1
print r2
Когда я запустил это, я вижу следующий вывод:
[[[2, 4, 6], [1, 4, 7]], {'a': [2, 4, 6]}]
[[[2, 4, 6], [1, 4, 7]]]
Вы можете видеть, что первая строка l
и d
, а вторая строка - это просто l
.
В моих кратких экспериментах я обнаружил, что результаты не всегда чисты. Например, внутри строк и кортежей есть больше источников, чем вы ожидали.