Simple tool/library to visualize huge python dict
I do not know of a ready-to-use tool, but you could use Traits UI to swiftly develop your own
from enthought.traits.api \ import HasTraits, Instancefrom enthought.traits.ui.api \ import View, VGroup, Item, ValueEditorclass DictEditor(HasTraits): Object = Instance( object ) def __init__(self, obj, **traits): super(DictEditor, self).__init__(**traits) self.Object = obj def trait_view(self, name=None, view_elements=None): return View( VGroup( Item( 'Object', label = 'Debug', id = 'debug', editor = ValueEditor(), style = 'custom', dock = 'horizontal', show_label = False ), ), title = 'Dictionary Editor', width = 800, height = 600, resizable = True, )def build_sample_data(): my_data = dict(zip(range(10),range(10,20))) my_data[11] = dict(zip(range(10),range(10,20))) my_data[11][11] = dict(zip(range(10),range(10,20))) return my_data# Testif __name__ == '__main__': my_data = build_sample_data() b = DictEditor(my_data) b.configure_traits()
That's it. You will have a GUI like:
Traits UI uses the Model-View-Controller approach to create GUI without having the need to programatically create every widget. Here, I use the predefined ValueEditor to display arbitrary types. You can now extend it to support searching, filtering etc...
EDIT
Simple extension to support filtering:
# -*- coding: utf-8 -*-"""Created on Fri Feb 22 12:52:28 2013@author: kranzth"""from enthought.traits.api \ import HasTraits, Instance, Str, on_trait_changefrom enthought.traits.ui.api \ import View, VGroup, Item, ValueEditor, TextEditorfrom copy import deepcopyclass DictEditor(HasTraits): SearchTerm = Str() Object = Instance( object ) def __init__(self, obj, **traits): super(DictEditor, self).__init__(**traits) self._original_object = obj self.Object = self._filter(obj) def trait_view(self, name=None, view_elements=None): return View( VGroup( Item( 'SearchTerm', label = 'Search:', id = 'search', editor = TextEditor(), #style = 'custom', dock = 'horizontal', show_label = True ), Item( 'Object', label = 'Debug', id = 'debug', editor = ValueEditor(), style = 'custom', dock = 'horizontal', show_label = False ), ), title = 'Dictionary Editor', width = 800, height = 600, resizable = True, ) @on_trait_change("SearchTerm") def search(self): self.Object = self._filter(self._original_object, self.SearchTerm) def _filter(self, object_, search_term=None): def has_matching_leaf(obj): if isinstance(obj, list): return any( map(has_matching_leaf, obj)) if isinstance(obj, dict): return any( map(has_matching_leaf, obj.values())) else: try: if not str(obj) == search_term: return False return True except ValueError: False obj = deepcopy(object_) if search_term is None: return obj if isinstance(obj, dict): for k in obj.keys(): if not has_matching_leaf(obj[k]): del obj[k] for k in obj.keys(): if isinstance(obj, dict): obj[k] = self._filter(obj[k], search_term) elif isinstance(obj, list): filter(has_matching_leaf,obj[k]) return objdef build_sample_data(): def make_one_level_dict(): return dict(zip(range(100), range(100,150) + map(str,range(150,200)))) my_data = make_one_level_dict() my_data[11] = make_one_level_dict() my_data[11][11] = make_one_level_dict() return my_data# Testif __name__ == '__main__': my_data = build_sample_data() b = DictEditor(my_data) b.configure_traits()
will give you a textbox with "filter-as-you-type". The search isn't completely correct for all cases, but you can figure out the idea.
Please note that in this sample the data in the dict are partly integers and partly strings, and both types will be found.
I'm finally ended up with converting my data into json
as @PavelAnossov suggested and using d3 Tree Layout.
There are some great answers already in here, but I believe this one qualifies as "simple" (it uses only python bult-in libraries tkinter and uuid).
It is based on John Gaines Jr.'s answer in another question, modified by Will Ware to support lists, modified by me to also support tuples (runs on python 3).
I've also reorganized it so that you can call the viewer with something as simple as tk_tree_view(data)
, passing in a dictionary (as in the example at the end).
import uuidimport tkinter as tkfrom tkinter import ttkdef j_tree(tree, parent, dic): for key in sorted(dic.keys()): uid = uuid.uuid4() if isinstance(dic[key], dict): tree.insert(parent, 'end', uid, text=key) j_tree(tree, uid, dic[key]) elif isinstance(dic[key], tuple): tree.insert(parent, 'end', uid, text=str(key) + '()') j_tree(tree, uid, dict([(i, x) for i, x in enumerate(dic[key])])) elif isinstance(dic[key], list): tree.insert(parent, 'end', uid, text=str(key) + '[]') j_tree(tree, uid, dict([(i, x) for i, x in enumerate(dic[key])])) else: value = dic[key] if isinstance(value, str): value = value.replace(' ', '_') tree.insert(parent, 'end', uid, text=key, value=value)def tk_tree_view(data): # Setup the root UI root = tk.Tk() root.title("tk_tree_view") root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) # Setup the Frames tree_frame = ttk.Frame(root, padding="3") tree_frame.grid(row=0, column=0, sticky=tk.NSEW) # Setup the Tree tree = ttk.Treeview(tree_frame, columns=('Values')) tree.column('Values', width=100, anchor='center') tree.heading('Values', text='Values') j_tree(tree, '', data) tree.pack(fill=tk.BOTH, expand=1) # Limit windows minimum dimensions root.update_idletasks() root.minsize(root.winfo_reqwidth(), root.winfo_reqheight()) root.mainloop()if __name__ == "__main__": # Setup some test data data = { "firstName": "John", "lastName": "Smith", "gender": "male", "age": 32, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021"}, "phoneNumbers": [ {"type": "home", "number": "212 555-1234"}, {"type": "fax", "number": "646 555-4567", "alphabet": [ "abc", "def", "ghi"] } ]} # call it with tk_tree_view(data)
It looks like this: