def test_it(collectible):
dd()
dd('======= ', ('collectible' if collectible else 'uncollectible'), ' object =======')
dd()
gc.collect()
dd('*** init, nr of referrers: ', len(gc.get_referrers(One)))
dd(' garbage: ', gc.garbage)
one = One(collectible)
dd(' created: ', one.typ, ': ', one)
dd(' nr of referrers: ', len(gc.get_referrers(One)))
dd(' delete:')
del one
gc.collect()
dd('*** after gc, nr of referrers: ', len(gc.get_referrers(One)))
dd(' garbage: ', gc.garbage)
python类get_referrers()的实例源码
def memory_dump():
import gc
x = 0
for obj in gc.get_objects():
i = id(obj)
size = sys.getsizeof(obj, 0)
# referrers = [id(o) for o in gc.get_referrers(obj)]
try:
cls = str(obj.__class__)
except:
cls = "<no class>"
if size > 1024 * 50:
referents = set([id(o) for o in gc.get_referents(obj)])
x += 1
print(x, {'id': i,
'class': cls,
'size': size,
"ref": len(referents)})
#if len(referents) < 2000:
#print(obj)
def load(self):
import iris
reload(iris)
reload(iris.config)
config = iris.config.load_config(sys.argv[1])
import iris.api
app = iris.api.get_api(config)
if not self.skip_build_assets:
for r in gc.get_referrers(self):
if isinstance(r, dict) and '_num_workers' in r:
gunicorn_arbiter = r
# only build assets on one worker to avoid race conditions
if gunicorn_arbiter['worker_age'] % self.options['workers'] == 0:
import iris.ui
iris.ui.build_assets()
return app
def getrefs(i, depth):
"""Get the i'th object in memory, return objects that reference it"""
import sys, gc, types
o = sys.getobjects(i)[-1]
for d in range(depth):
for ref in gc.get_referrers(o):
if type(ref) in (types.ListType, types.DictType,
types.InstanceType):
if type(ref) is types.DictType and ref.has_key('copyright'):
continue
o = ref
break
else:
print "Max depth ", d
return o
return o
def _fix_py3_rlock(old):
import gc
import threading
new = threading._PyRLock()
while old._is_owned():
old.release()
new.acquire()
if old._is_owned():
new.acquire()
gc.collect()
for ref in gc.get_referrers(old):
try:
ref_vars = vars(ref)
except TypeError:
pass
else:
for k, v in ref_vars.items():
if v == old:
setattr(ref, k, new)
def __await__(self):
def exec_when_ready():
event.wait()
coro.send(None)
if not self.exited:
raise RuntimeError('attempted to "await" in a worker thread')
if self.exited:
# This is run in the worker thread
yield
else:
# This is run in the event loop thread
previous_frame = inspect.currentframe().f_back
coro = next(obj for obj in gc.get_referrers(previous_frame.f_code)
if inspect.iscoroutine(obj) and obj.cr_frame is previous_frame)
event = Event()
loop = get_event_loop()
future = loop.run_in_executor(self.executor, exec_when_ready)
next(future.__await__()) # Make the future think it's being awaited on
loop.call_soon(event.set)
yield future
def file_module_function_of(self, frame):
code = frame.f_code
filename = code.co_filename
if filename:
modulename = modname(filename)
else:
modulename = None
funcname = code.co_name
clsname = None
if code in self._caller_cache:
if self._caller_cache[code] is not None:
clsname = self._caller_cache[code]
else:
self._caller_cache[code] = None
## use of gc.get_referrers() was suggested by Michael Hudson
# all functions which refer to this code object
funcs = [f for f in gc.get_referrers(code)
if inspect.isfunction(f)]
# require len(func) == 1 to avoid ambiguity caused by calls to
# new.function(): "In the face of ambiguity, refuse the
# temptation to guess."
if len(funcs) == 1:
dicts = [d for d in gc.get_referrers(funcs[0])
if isinstance(d, dict)]
if len(dicts) == 1:
classes = [c for c in gc.get_referrers(dicts[0])
if hasattr(c, "__bases__")]
if len(classes) == 1:
# ditto for new.classobj()
clsname = classes[0].__name__
# cache the result - assumption is that new.* is
# not called later to disturb this relationship
# _caller_cache could be flushed if functions in
# the new module get called.
self._caller_cache[code] = clsname
if clsname is not None:
funcname = "%s.%s" % (clsname, funcname)
return filename, modulename, funcname
def describeObj(obj, depth=4, path=None, ignore=None):
"""
Trace all reference paths backward, printing a list of different ways this object can be accessed.
Attempts to answer the question "who has a reference to this object"
"""
if path is None:
path = [obj]
if ignore is None:
ignore = {} ## holds IDs of objects used within the function.
ignore[id(sys._getframe())] = None
ignore[id(path)] = None
gc.collect()
refs = gc.get_referrers(obj)
ignore[id(refs)] = None
printed=False
for ref in refs:
if id(ref) in ignore:
continue
if id(ref) in list(map(id, path)):
print("Cyclic reference: " + refPathString([ref]+path))
printed = True
continue
newPath = [ref]+path
if len(newPath) >= depth:
refStr = refPathString(newPath)
if '[_]' not in refStr: ## ignore '_' references generated by the interactive shell
print(refStr)
printed = True
else:
describeObj(ref, depth, newPath, ignore)
printed = True
if not printed:
print("Dead end: " + refPathString(path))
def describeObj(obj, depth=4, path=None, ignore=None):
"""
Trace all reference paths backward, printing a list of different ways this object can be accessed.
Attempts to answer the question "who has a reference to this object"
"""
if path is None:
path = [obj]
if ignore is None:
ignore = {} ## holds IDs of objects used within the function.
ignore[id(sys._getframe())] = None
ignore[id(path)] = None
gc.collect()
refs = gc.get_referrers(obj)
ignore[id(refs)] = None
printed=False
for ref in refs:
if id(ref) in ignore:
continue
if id(ref) in list(map(id, path)):
print("Cyclic reference: " + refPathString([ref]+path))
printed = True
continue
newPath = [ref]+path
if len(newPath) >= depth:
refStr = refPathString(newPath)
if '[_]' not in refStr: ## ignore '_' references generated by the interactive shell
print(refStr)
printed = True
else:
describeObj(ref, depth, newPath, ignore)
printed = True
if not printed:
print("Dead end: " + refPathString(path))
def __getstate__(self):
log.msg( "WARNING: serializing ephemeral %s" % self )
import gc
for r in gc.get_referrers(self):
log.msg( " referred to by %s" % (r,))
return None
def file_module_function_of(self, frame):
code = frame.f_code
filename = code.co_filename
if filename:
modulename = modname(filename)
else:
modulename = None
funcname = code.co_name
clsname = None
if code in self._caller_cache:
if self._caller_cache[code] is not None:
clsname = self._caller_cache[code]
else:
self._caller_cache[code] = None
## use of gc.get_referrers() was suggested by Michael Hudson
# all functions which refer to this code object
funcs = [f for f in gc.get_referrers(code)
if inspect.isfunction(f)]
# require len(func) == 1 to avoid ambiguity caused by calls to
# new.function(): "In the face of ambiguity, refuse the
# temptation to guess."
if len(funcs) == 1:
dicts = [d for d in gc.get_referrers(funcs[0])
if isinstance(d, dict)]
if len(dicts) == 1:
classes = [c for c in gc.get_referrers(dicts[0])
if hasattr(c, "__bases__")]
if len(classes) == 1:
# ditto for new.classobj()
clsname = classes[0].__name__
# cache the result - assumption is that new.* is
# not called later to disturb this relationship
# _caller_cache could be flushed if functions in
# the new module get called.
self._caller_cache[code] = clsname
if clsname is not None:
funcname = "%s.%s" % (clsname, funcname)
return filename, modulename, funcname
def find_referring_graphs(obj):
print('Looking for references to {!r}'.format(obj))
referrers = (r for r in gc.get_referrers(obj)
if r not in REFERRERS_TO_IGNORE)
for ref in referrers:
if isinstance(ref, Graph):
# A graph node
yield ref
elif isinstance(ref, dict):
# An instance or other namespace dictionary
for parent in find_referring_graphs(ref):
yield parent
# Look for objects that refer to the objects in the graph.
def dump_garbage():
print "\nGARBAGE:"
gc.collect()
print "\nGARBAGE OBJECTS:"
for x in gc.garbage:
print_with_type (x)
if isinstance(x, arrivals.Event):
print "REFERS:"
for y in gc.get_referrers (x):
print_with_type (y)
print "End refers"
def test_old_callback_forgotten(self):
"""
If `Context.set_tlsext_servername_callback` is used to specify
a new callback, the one it replaces is dereferenced.
"""
def callback(connection): # pragma: no cover
pass
def replacement(connection): # pragma: no cover
pass
context = Context(TLSv1_METHOD)
context.set_tlsext_servername_callback(callback)
tracker = ref(callback)
del callback
context.set_tlsext_servername_callback(replacement)
# One run of the garbage collector happens to work on CPython. PyPy
# doesn't collect the underlying object until a second run for whatever
# reason. That's fine, it still demonstrates our code has properly
# dropped the reference.
collect()
collect()
callback = tracker()
if callback is not None:
referrers = get_referrers(callback)
if len(referrers) > 1: # pragma: nocover
pytest.fail("Some references remain: %r" % (referrers,))
def g():
marker = object()
yield marker
# now the marker is in the tuple being constructed
[tup] = [x for x in gc.get_referrers(marker) if type(x) is tuple]
print(tup)
print(tup[1])
def g():
marker = object()
yield marker
# now the marker is in the tuple being constructed
[tup] = [x for x in gc.get_referrers(marker) if type(x) is tuple]
print tup
print tup[1]
def file_module_function_of(self, frame):
code = frame.f_code
filename = code.co_filename
if filename:
modulename = modname(filename)
else:
modulename = None
funcname = code.co_name
clsname = None
if code in self._caller_cache:
if self._caller_cache[code] is not None:
clsname = self._caller_cache[code]
else:
self._caller_cache[code] = None
## use of gc.get_referrers() was suggested by Michael Hudson
# all functions which refer to this code object
funcs = [f for f in gc.get_referrers(code)
if inspect.isfunction(f)]
# require len(func) == 1 to avoid ambiguity caused by calls to
# new.function(): "In the face of ambiguity, refuse the
# temptation to guess."
if len(funcs) == 1:
dicts = [d for d in gc.get_referrers(funcs[0])
if isinstance(d, dict)]
if len(dicts) == 1:
classes = [c for c in gc.get_referrers(dicts[0])
if hasattr(c, "__bases__")]
if len(classes) == 1:
# ditto for new.classobj()
clsname = classes[0].__name__
# cache the result - assumption is that new.* is
# not called later to disturb this relationship
# _caller_cache could be flushed if functions in
# the new module get called.
self._caller_cache[code] = clsname
if clsname is not None:
funcname = "%s.%s" % (clsname, funcname)
return filename, modulename, funcname
def g():
marker = object()
yield marker
# now the marker is in the tuple being constructed
[tup] = [x for x in gc.get_referrers(marker) if type(x) is tuple]
print tup
print tup[1]
def file_module_function_of(self, frame):
code = frame.f_code
filename = code.co_filename
if filename:
modulename = modname(filename)
else:
modulename = None
funcname = code.co_name
clsname = None
if code in self._caller_cache:
if self._caller_cache[code] is not None:
clsname = self._caller_cache[code]
else:
self._caller_cache[code] = None
## use of gc.get_referrers() was suggested by Michael Hudson
# all functions which refer to this code object
funcs = [f for f in gc.get_referrers(code)
if inspect.isfunction(f)]
# require len(func) == 1 to avoid ambiguity caused by calls to
# new.function(): "In the face of ambiguity, refuse the
# temptation to guess."
if len(funcs) == 1:
dicts = [d for d in gc.get_referrers(funcs[0])
if isinstance(d, dict)]
if len(dicts) == 1:
classes = [c for c in gc.get_referrers(dicts[0])
if hasattr(c, "__bases__")]
if len(classes) == 1:
# ditto for new.classobj()
clsname = classes[0].__name__
# cache the result - assumption is that new.* is
# not called later to disturb this relationship
# _caller_cache could be flushed if functions in
# the new module get called.
self._caller_cache[code] = clsname
if clsname is not None:
funcname = "%s.%s" % (clsname, funcname)
return filename, modulename, funcname
def __getstate__(self):
log.msg( "WARNING: serializing ephemeral %s" % self )
import gc
for r in gc.get_referrers(self):
log.msg( " referred to by %s" % (r,))
return None
def file_module_function_of(self, frame):
code = frame.f_code
filename = code.co_filename
if filename:
modulename = modname(filename)
else:
modulename = None
funcname = code.co_name
clsname = None
if code in self._caller_cache:
if self._caller_cache[code] is not None:
clsname = self._caller_cache[code]
else:
self._caller_cache[code] = None
## use of gc.get_referrers() was suggested by Michael Hudson
# all functions which refer to this code object
funcs = [f for f in gc.get_referrers(code)
if inspect.isfunction(f)]
# require len(func) == 1 to avoid ambiguity caused by calls to
# new.function(): "In the face of ambiguity, refuse the
# temptation to guess."
if len(funcs) == 1:
dicts = [d for d in gc.get_referrers(funcs[0])
if isinstance(d, dict)]
if len(dicts) == 1:
classes = [c for c in gc.get_referrers(dicts[0])
if hasattr(c, "__bases__")]
if len(classes) == 1:
# ditto for new.classobj()
clsname = classes[0].__name__
# cache the result - assumption is that new.* is
# not called later to disturb this relationship
# _caller_cache could be flushed if functions in
# the new module get called.
self._caller_cache[code] = clsname
if clsname is not None:
funcname = "%s.%s" % (clsname, funcname)
return filename, modulename, funcname
def Notify(self):
for o in self.observers:
o = o()
try:
import gc
except ImportError:
o = None #some jython does not have gc, so, there's no sense testing this in it
else:
try:
gc.get_referrers(o)
except:
o = None #jython and ironpython do not have get_referrers
if o is not None:
sys.stdout.write('still observing %s\n' % (o,))
sys.stdout.write('number of referrers: %s\n' % len(gc.get_referrers(o)))
frame = gc.get_referrers(o)[0]
frame_referrers = gc.get_referrers(frame)
sys.stdout.write('frame referrer %s\n' % (frame_referrers,))
referrers1 = gc.get_referrers(frame_referrers[1])
sys.stdout.write('%s\n' % (referrers1,))
sys.stderr.write('TEST FAILED: The observer should have died, even when running in debug\n')
else:
sys.stdout.write('TEST SUCEEDED: observer died\n')
sys.stdout.flush()
sys.stderr.flush()
def g():
marker = object()
yield marker
# now the marker is in the tuple being constructed
[tup] = [x for x in gc.get_referrers(marker) if type(x) is tuple]
print(tup)
print(tup[1])
def test_old_callback_forgotten(self):
"""
If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
callback, the one it replaces is dereferenced.
"""
def callback(connection):
pass
def replacement(connection):
pass
context = Context(TLSv1_METHOD)
context.set_tlsext_servername_callback(callback)
tracker = ref(callback)
del callback
context.set_tlsext_servername_callback(replacement)
# One run of the garbage collector happens to work on CPython. PyPy
# doesn't collect the underlying object until a second run for whatever
# reason. That's fine, it still demonstrates our code has properly
# dropped the reference.
collect()
collect()
callback = tracker()
if callback is not None:
referrers = get_referrers(callback)
if len(referrers) > 1:
self.fail("Some references remain: %r" % (referrers,))
def report_uncollectable():
import gc
if not gc.garbage:
print("No garbages!")
return
print('uncollectable objects')
for obj in gc.garbage:
print(obj)
if hasattr(obj, '__dict__'):
print(obj.__dict__)
for ref in gc.get_referrers(obj):
print("referrer:", ref)
print('---')
def _fix_py3_rlock(old):
import gc
import threading
new = threading._PyRLock()
while old._is_owned():
old.release()
new.acquire()
if old._is_owned():
new.acquire()
gc.collect()
for ref in gc.get_referrers(old):
for k, v in vars(ref):
if v == old:
setattr(ref, k, new)
def rainMove(self, value):
for instance in (obj for obj in gc.get_referrers(self.__class__) if isinstance(obj, self.__class__)):
instance.rainPosition -= value
def ascend(self, obj, depth=1):
"""Return a nested list containing referrers of the given object."""
depth += 1
parents = []
# Gather all referrers in one step to minimize
# cascading references due to repr() logic.
refs = gc.get_referrers(obj)
self.ignore.append(refs)
if len(refs) > self.maxparents:
return [('[%s referrers]' % len(refs), [])]
try:
ascendcode = self.ascend.__code__
except AttributeError:
ascendcode = self.ascend.im_func.func_code
for parent in refs:
if inspect.isframe(parent) and parent.f_code is ascendcode:
continue
if parent in self.ignore:
continue
if depth <= self.maxdepth:
parents.append((parent, self.ascend(parent, depth)))
else:
parents.append((parent, []))
return parents
def g():
marker = object()
yield marker
# now the marker is in the tuple being constructed
[tup] = [x for x in gc.get_referrers(marker) if type(x) is tuple]
print(tup)
print(tup[1])
def file_module_function_of(self, frame):
code = frame.f_code
filename = code.co_filename
if filename:
modulename = _modname(filename)
else:
modulename = None
funcname = code.co_name
clsname = None
if code in self._caller_cache:
if self._caller_cache[code] is not None:
clsname = self._caller_cache[code]
else:
self._caller_cache[code] = None
## use of gc.get_referrers() was suggested by Michael Hudson
# all functions which refer to this code object
funcs = [f for f in gc.get_referrers(code)
if inspect.isfunction(f)]
# require len(func) == 1 to avoid ambiguity caused by calls to
# new.function(): "In the face of ambiguity, refuse the
# temptation to guess."
if len(funcs) == 1:
dicts = [d for d in gc.get_referrers(funcs[0])
if isinstance(d, dict)]
if len(dicts) == 1:
classes = [c for c in gc.get_referrers(dicts[0])
if hasattr(c, "__bases__")]
if len(classes) == 1:
# ditto for new.classobj()
clsname = classes[0].__name__
# cache the result - assumption is that new.* is
# not called later to disturb this relationship
# _caller_cache could be flushed if functions in
# the new module get called.
self._caller_cache[code] = clsname
if clsname is not None:
funcname = "%s.%s" % (clsname, funcname)
return filename, modulename, funcname