Last active
August 29, 2015 13:55
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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