Используя gc
интерфейс сборщика мусора в Python и sys.getsizeof()
можно сбросить все объекты Python и их размеры. Вот код, который я использую в производстве для устранения утечки памяти:
rss = psutil.Process(os.getpid()).get_memory_info().rss
# Dump variables if using more than 100MB of memory
if rss > 100 * 1024 * 1024:
memory_dump()
os.abort()
def memory_dump():
dump = open("memory.pickle", 'wb')
xs = []
for obj in gc.get_objects():
i = id(obj)
size = sys.getsizeof(obj, 0)
# referrers = [id(o) for o in gc.get_referrers(obj) if hasattr(o, '__class__')]
referents = [id(o) for o in gc.get_referents(obj) if hasattr(o, '__class__')]
if hasattr(obj, '__class__'):
cls = str(obj.__class__)
xs.append({'id': i, 'class': cls, 'size': size, 'referents': referents})
cPickle.dump(xs, dump)
Обратите внимание, что я сохраняю данные только из объектов, которые имеют атрибут __class__
, потому что это единственные объекты, которые меня волнуют. Должна быть возможность сохранить полный список объектов, но вам нужно будет позаботиться о выборе других атрибутов. Кроме того, я обнаружил, что получение ссылок для каждого объекта было чрезвычайно медленным, поэтому я решил сохранить только ссылки. В любом случае, после сбоя результирующие данные могут быть прочитаны следующим образом:
with open("memory.pickle", 'rb') as dump:
objs = cPickle.load(dump)
Добавлено 2017-11-15
Версия Python 3.6 находится здесь:
import gc
import sys
import _pickle as cPickle
def memory_dump():
with open("memory.pickle", 'wb') as dump:
xs = []
for obj in gc.get_objects():
i = id(obj)
size = sys.getsizeof(obj, 0)
# referrers = [id(o) for o in gc.get_referrers(obj) if hasattr(o, '__class__')]
referents = [id(o) for o in gc.get_referents(obj) if hasattr(o, '__class__')]
if hasattr(obj, '__class__'):
cls = str(obj.__class__)
xs.append({'id': i, 'class': cls, 'size': size, 'referents': referents})
cPickle.dump(xs, dump)