def get_size(obj, seen=None): """Recursively finds size of objects in bytes""" size = sys.getsizeof(obj) if seen isNone: seen = set() obj_id = id(obj) if obj_id in seen: return0 # Important mark as seen *before* entering recursion to gracefully handle # self-referential objects seen.add(obj_id) if
hasattr(obj, '__dict__'): for cls in obj.__class__.__mro__: if'__dict__'in cls.__dict__: d = cls.__dict__['__dict__'] if inspect.isgetsetdescriptor(d) or inspect.ismemberdescriptor(d): size += get_size(obj.__dict__, seen) break if isinstance(obj, dict): size += sum((get_size(v, seen) for v in obj.values())) size += sum((get_size(k, seen) for k in obj.keys())) elif hasattr(obj, '__iter__') andnot isinstance(obj, (str, bytes, bytearray)): size += sum((get_size(i, seen) for i in obj))
if hasattr(obj, '__slots__'): # can have __slots__ with __dict__ size += sum(get_size(getattr(obj, s), seen) for s in obj.__slots__ if hasattr(obj, s))
defasizeof(self, *objs, **opts): '''Return the combined size of the given objects (with modified options, see method **set**). ''' if opts: self.set(**opts) self.exclude_refs(*objs) # skip refs to objs return sum(self._sizer(o, 0, 0, None) for o in objs)
def_sizer(self, obj, pid, deep, sized):# MCCABE 19 '''Size an object, recursively. ''' s, f, i = 0, 0, id(obj) if i not
in self._seen: self._seen[i] = 1 elif deep or self._seen[i]: # skip obj if seen before # or if ref of a given obj self._seen.again(i) if sized: s = sized(s, f, name=self._nameof(obj)) self.exclude_objs(s) return s # zero else: # deep == seen[i] == 0 self._seen.again(i) try: k, rs = _objkey(obj), [] if k in self._excl_d: self._excl_d[k] += 1 else: v = _typedefs.get(k, None) ifnot v: # new typedef _typedefs[k] = v = _typedef(obj, derive=self._derive_, frames=self._frames_, infer=self._infer_) if (v.both or self._code_) and v.kind isnot self._ign_d: # 猫注:这里计算 flat size s = f = v.flat(obj, self._mask) # flat size if self._profile: # profile based on *flat* size self._prof(k).update(obj, s) # recurse, but not for nested modules if v.refs and deep andnot (deep and ismodule(obj)): # add sizes of referents z, d = self._sizer, deep + 1 if sized and deep # use named referents self.exclude_objs(rs) for o in v.refs(obj, True): if isinstance(o, _NamedRef): r = z(o.ref, i, d, sized) r.name = o.name else: r = z(o, i, d, sized) r.name = self._nameof(o) rs.append(r) s += r.size else: # just size and accumulate for o in v.refs(obj, False): # 猫注:这里递归计算 item size s += z(o, i, d, None) # deepest recursion reached if self._depth self._depth = d if self._stats_ and s > self._above_ > 0: # rank based on *total* size self._rank(k, obj, s, deep, pid) except RuntimeError: # XXX RecursionLimitExceeded: self._missed += 1 ifnot deep: self._total += s # accumulate if sized: s = sized(s, f, name=self._nameof(obj), refs=rs) self.exclude_objs(s) return s