Skip to content

Instantly share code, notes, and snippets.

@kurtbrose
Last active August 29, 2015 13:55
Show Gist options
  • Select an option

  • Save kurtbrose/8705967 to your computer and use it in GitHub Desktop.

Select an option

Save kurtbrose/8705967 to your computer and use it in GitHub Desktop.
Very early bones of a Tkinter object browsing GUI. Should be useful for debugging GC.
import threading
import functools
import gc
import types
class ObjBrowserThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
self.start()
def run(self):
global tk
import Tkinter as tk
self.root = tk.Tk()
self.root.protocol("WM_DELETE_WINDOW", lambda: self.root.quit())
self.left = _ReferenceFrame(tk.Frame(self.root), self)
self.left.frame.grid(row=10, column=10, sticky='n')
self.center = tk.Frame(self.root)
self.center.grid(row=10, column=20, sticky='n', padx=20)
self.right = _ReferenceFrame(tk.Frame(self.root), self)
self.right.frame.grid(row=10, column=30, sticky='n')
self.type_label = tk.Label(self.center, text="type")
self.type_label.grid(row=10)
self.type_name = tk.StringVar()
self.type = tk.Label(self.center, textvariable=self.type_name)
self.type.grid(row=20)
self.show_button = tk.Button(self.center, text="show", command=self.show_id)
self.show_button.grid(row=30)
self.id_entry = tk.Entry(self.center)
self.id_entry.grid(row=40)
self.set_obj(types) #self)
self.root.mainloop()
def show_id(self):
try:
new_id = int(self.id_entry.get())
except ValueError:
print "self.id_entry.get() not a valid id", new_id
return
for obj in gc.get_objects():
if id(obj) == new_id:
break
else:
print "could not find", new_id, "in gc.get_objects()"
return
self.set_obj(obj)
def set_obj(self, obj):
self.id_entry.delete(0, tk.END)
self.id_entry.insert(0, id(obj))
self.left.clear()
self.left.setrefs(get_referrer_key_obj_list(obj))
if isinstance(obj, dict):
self.right.setrefs(obj.items())
elif isinstance(obj, list):
self.right.setrefs(enumerate(obj))
elif hasattr(obj, "__dict__"):
self.right.setrefs(obj.__dict__.items())
self.type_name.set(type(obj).__name__)
class _ReferenceFrame(object):
def __init__(self, frame, obj_browser):
self.frame = frame
self.inner = tk.Frame(self.frame)
self.obj_browser = obj_browser
def setrefs(self, refs):
self.inner.destroy()
self.inner = tk.Frame(self.frame)
row = 10
for k, v in refs:
tk.Label(self.inner, text=tolabel(k)).grid(row=row, column=10, sticky='e')
tk.Button(
self.inner,
text=tolabel(v),
command=functools.partial(self.obj_browser.set_obj, v)
).grid(row=row, column=20, sticky='w')
row += 10
self.inner.pack()
def clear(self):
self.inner.destroy()
def pack(self):
self.inner.pack()
self.frame.pack()
def get_referrer_key_obj_list(obj):
'''
Return a list [ (key, ref), (key, ref), ...]
Where key is a string representing how the object
ref references the passed obj.
'''
gc.collect()
refs = gc.get_referrers(obj)
key_obj_list = []
for e in refs:
key = None
if isinstance(e, dict):
key = "[" + repr(keyof(e, obj)) + "]"
elif isinstance(e, (list, tuple)):
try:
key = "[" + repr(e.index(obj)) + "]"
except ValueError:
pass
elif isinstance(e, types.FrameType):
key = keyof(e.f_locals, obj) or keyof(e.f_globals, obj)
elif isinstance(e, types.MethodType):
key = keyof(
{ "im_class": e.im_class,
"im_func": e.im_func,
"im_self": e.im_self
}, obj)
elif hasattr(e, '__dict__'):
key = keyof(e.__dict__, obj)
# if all else has failed...
if type(e) is obj:
key = '__class__'
key_obj_list.append((key, e))
return key_obj_list
def keyof(map, obj):
'find key that obj is stored at in map by exhaustive search'
for k in map:
if map[k] is obj:
return k
return None
def tolabel(obj):
if not isinstance(obj, basestring):
obj = repr(obj)
return obj.encode('utf-8', 'replace')[:64]
class ObjGLThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
self.start()
def run(self):
global pyglet
import pyglet
self.window = pyglet.window.Window()
label = pyglet.text.Label(
'Hello, world',
font_name='Times New Roman',
font_size=36,
x=self.window.width//2, y=self.window.height//2,
anchor_x='center', anchor_y='center')
@self.window.event
def on_draw():
self.window.clear()
label.draw()
pyglet.app.run()
if __name__ == "__main__":
try:
ObjBrowserThread()
ObjGLThread()
except:
import traceback; traceback.print_exc()
import pdb; pdb.post_mortem()
raw_input("press Enter to close window and exit...")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment