简单的工具/库可视化巨大的python dict

lig*_*lig 12 python gtk user-interface dictionary tkinter

我有一个像这样的巨大的字典结构:

my_data = {
    'key1': {
        '_': 'value1': 'aaa'
    },
    'key2': {
        '_': 'value2': 'bbb',
        'key2.1': {
            '_': 'ccc',
            'key2.1.1': {
                '_': 'ddd'
            }
        }
        'key2.2': {
            '_': 'eee',
            'key2.2.1': {
                '_': 'fff'
            }
            'key2.2.2': {
                '_': 'ggg'
            }               
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

等等.

我希望以一种树形式向用户显示它,使用GTK,TK或任何能够浏览它的东西可以折叠和扩展分支并可能搜索键和值.

可能我不需要手工开发这样的工具,并且已经有一些东西可以直观地显示这种数据?

Tho*_*anz 9

我不知道一个现成的工具,但您可以使用Traits UI快速开发自己的工具

from enthought.traits.api \
    import HasTraits, Instance

from enthought.traits.ui.api \
    import View, VGroup, Item, ValueEditor

class 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

# Test
if __name__ == '__main__':
    my_data = build_sample_data()
    b = DictEditor(my_data)
    b.configure_traits()
Run Code Online (Sandbox Code Playgroud)

而已.您将拥有如下GUI:

Traits UI使用模型 - 视图 - 控制器方法创建GUI,而无需以编程方式创建每个小部件.在这里,我使用预定义的ValueEditor来显示任意类型.您现在可以扩展它以支持搜索,过滤等...在此输入图像描述

编辑

支持过滤的简单扩展:

# -*- coding: utf-8 -*-
"""
Created on Fri Feb 22 12:52:28 2013

@author: kranzth
"""
from enthought.traits.api \
    import HasTraits, Instance, Str, on_trait_change

from enthought.traits.ui.api \
    import View, VGroup, Item, ValueEditor, TextEditor

from copy import deepcopy

class 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 obj



def 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

# Test
if __name__ == '__main__':
    my_data = build_sample_data()
    b = DictEditor(my_data)
    b.configure_traits()
Run Code Online (Sandbox Code Playgroud)

会给你一个带有"按类型过滤"的文本框.对于所有情况,搜索并不完全正确,但您可以找出想法.

请注意,在此示例中,dict中的数据部分是整数,部分是字符串,两种类型都可以找到.

在此输入图像描述


lig*_*lig 9

我终于将我的数据转换json为@PavelAnossov建议并使用d3树布局.

在此输入图像描述


Luc*_*ira 9

这里已经有了一些很好的答案,但我相信这个问题可以说是"简单"(它只使用python bult-in库tkinter和uuid).

它基于John Gaines Jr.在另一个问题中的答案,由Will Ware修改为支持列表,由我修改以支持元组(在python 3上运行).

我还重新组织了它,这样你就可以用一些简单的东西来调用查看器tk_tree_view(data),传入字典(如最后的例子).

import uuid
import tkinter as tk
from tkinter import ttk


def 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)
Run Code Online (Sandbox Code Playgroud)

它看起来像这样:

在此输入图像描述