Source code for mmf.utils.debug
"""Debugging tools"""
import sys,inspect
import gc
import weakref
[docs]class Memory(object):
"""This class represents the current state of memory.
Example: (Don't run these with code coverage testing or else you
may run out of memory!)
>> m = Memory() # doctest: +ELLIPSIS
Checkpointed ... objects.
>> m.new() # Now look at new objects
"""
[docs] def __init__(self):
self._all = {}
self._ignore = set()
self.ignore(self._all)
self.ignore(self._ignore)
# Ignore all memory management variables
seen = set(self._ignore)
self.ignore(seen)
all = {}
unreachable = gc.collect()
self._getrec(gc.get_referents(self),all_=all,seen_=seen)
self.ignore(all)
for k in all:
self.ignore(k)
del all
del seen
self.checkpoint()
[docs] def ignore(self,e):
"""Ignore the specified object."""
self._ignore.add(id(e))
[docs] def checkpoint(self):
"""Take a snapshot of the current state of the memory."""
self._all.clear()
seen = set(self._ignore)
self.ignore(seen)
unreachable = gc.collect()
objects = gc.get_objects()
self.ignore(objects)
self._getrec(objects,all_=self._all,seen_=seen)
print "Checkpointed %i objects."%len(self._all)
[docs] def new(self):
"""Return a dictionary of all new objects."""
gc.collect()
objects = gc.get_objects()
seen = set()
all = {}
seen.add(id(objects))
seen.add(id(seen))
seen.add(id(all))
frame = sys._getframe()
seen.add(id(frame))
seen.add(id(frame.f_back))
all.clear()
self._getrec(objects,all,seen)
return [(k,all[k]) for k in all if k not in self._all]
def _getrec(self,slist,all_,seen_):
"""Recursively process all objects in slist and add all objects to
the dictionary all_ except those with id's in the set seen_."""
for e in slist:
ide = id(e)
if ide in seen_ or ide in self._ignore:
continue
seen_.add(ide)
all_[ide] = e
referents = gc.get_referents(e)
seen_.add(id(referents))
if referents:
self._getrec(referents,all_,seen_)
del referents
def _getr(slist, olist, seen):
"""Recursively expand slist's objects into olist, using seen to track
already processed objects."""
for e in slist:
if id(e) in seen:
continue
seen[id(e)] = None
olist.append(e)
unreachable = gc.collect()
tl = gc.get_referents(e)
if tl:
_getr(tl, olist, seen)
def _getr(slist,all_,seen_):
"""Recursively expand slist's object id's into id_set, using seen to track
already processed objects."""
for e in slist:
eid = id(e)
if eid in all_ or eid in seen_:
continue
seen_.add(eid)
all_[eid] = e
tl = gc.get_referents(e)
seen_.add(id(eid))
if tl:
_getr(tl,all_,seen_)
# The public function.
[docs]def get_all_objects():
"""Return a list of all live Python
objects, not including the list itself."""
gcl = gc.get_objects()
all = {}
seen = set()
# Just in case:
seen.add(id(gcl))
seen.add(id(all))
seen.add(id(seen))
# _getr does the real work.
_getr(gcl, all, seen)
return all
_checkpoint_ids = set()
[docs]def check_point():
"""Set a checkpoint consisting of the current objects in memory."""
_checkpoint_ids.clear()
all = get_all_objects()
_checkpoint_ids.update(all)
del all
[docs]def new():
"""Set a checkpoint consisting of the current objects in memory."""
gc.collect()
all = get_all_objects()
ans = dict((k,all[k]) for k in all if k not in _checkpoint_ids)
[docs]def count_objects():
"""Return the number of objects alive."""
gc.collect()
n = len(get_all_objects())
gc.collect()
return n