2010-11-29 124 views
80

我喜欢Python中的pprint模块。我用它进行测试和调试。我经常使用宽度选项来确保输出很好地适合我的终端窗口。任何正确漂亮打印有序字典的方法?

它工作得很好,直到他们在Python 2.7中添加了新的ordered dictionary type(我真的很喜欢另一个很酷的功能)。如果我试图漂亮地打印有序字典,它不会很好地显示。而不是让每一个键值对自己行,整个事情就会出现在一条长长的行上,这个行很多次,很难阅读。

有没有人有办法让它打印很好,就像旧的无序字典一样?如果我花了足够的时间,我可能会想出一些东西,可能使用PrettyPrinter.format方法,但我想知道是否有人在这里已经知道解决方案。

更新:我为此提交了一个错误报告。你可以在http://bugs.python.org/issue10592看到它。

+6

可能要考虑打开一个bug。 – 2010-11-29 05:29:59

+0

我正在考虑这样做。我会在这里发布更新,如果我这样做。 – 2010-11-29 05:36:13

+1

建议添加有关有序字典的评论到http://bugs.python.org/issue7434 – 2010-11-29 08:51:32

回答

2
def pprint_od(od): 
    print "{" 
    for key in od: 
     print "%s:%s,\n" % (key, od[key]) # Fixed syntax 
    print "}" 

你去那里^^

for item in li: 
    pprint_od(item) 

(pprint_od(item) for item in li) 
+0

我正在寻找一种方法来有一个功能,可以漂亮地打印OrderedDicts以及其他类型。我没有看到我将如何使用你的函数来漂亮地打印OrderedDicts列表。 – 2010-11-29 05:38:53

+0

让我对它进行修改 – 2010-11-29 05:40:52

+0

-1'pprint_od()`函数不起作用 - 对于key中的项,od语句中的项产生'ValueError:太多的值来解压缩*和*唯一的输出是缩进的在`print`语句中最后的``}“`*和*`key,item`需要在括号中。你去了^^ – martineau 2010-11-29 09:33:14

10

下面的工作,如果你的OrderedDict的顺序是字母排序,因为pprint将整理打印前的字典。

pprint(dict(o.items())) 
+2

由于OrderedDicts按插入顺序排序,所以这可能适用于一小部分使用。无论如何,将OD转换为“dict”应该避免将所有内容放在一行上。 – martineau 2010-11-29 09:07:51

0

你可以重新定义为OrderedDictpprint()和拦截来电。这是一个简单的例子。如所写的,OrderedDict覆盖代码忽略任何可能已经通过但可以增强以实现它们的可选streamindent,widthdepth关键字。但这种方法不处理他们另一个容器内,比如一个listOrderDict

from collections import OrderedDict 
from pprint import pprint as pp_pprint 

def pprint(obj, *args, **kwrds): 
    if not isinstance(obj, OrderedDict): 
     # use stock function 
     return pp_pprint(obj, *args, **kwrds) 
    else: 
     # very simple sample custom implementation... 
     print "{" 
     for key in obj: 
      print " %r:%r" % (key, obj[key]) 
     print "}" 

l = [10, 2, 4] 
d = dict((('john',1), ('paul',2), ('mary',3))) 
od = OrderedDict((('john',1), ('paul',2), ('mary',3))) 
pprint(l, width=4) 
# [10, 
# 2, 
# 4] 
pprint(d) 
# {'john': 1, 'mary': 3, 'paul': 2} 

pprint(od) 
# { 
#  'john':1 
#  'paul':2 
#  'mary':3 
# } 
8

下面是通过覆盖和使用内部股票pprint()功能中的另一种答案。不像我的earlier one处理OrderedDict的另一个容器,如list的内部,并且还应该能够处理给定的任何可选关键字参数 - 但它没有控制另一个输出提供的输出相同程度的控制。

它通过将库存函数的输出重定向到一个临时缓冲区进行操作,然后在将它发送到输出流之前将其换行。虽然最终产出并不是特别漂亮,但它很体面,可能“足够好”可以用作解决方法。

更新2.0

通过使用标准库textwrap模块简化,并且修改 Python 2中& 3两者工作。

from collections import OrderedDict 
try: 
    from cStringIO import StringIO 
except ImportError: # Python 3 
    from io import StringIO 
from pprint import pprint as pp_pprint 
import sys 
import textwrap 

def pprint(object, **kwrds): 
    try: 
     width = kwrds['width'] 
    except KeyError: # unlimited, use stock function 
     pp_pprint(object, **kwrds) 
     return 
    buffer = StringIO() 
    stream = kwrds.get('stream', sys.stdout) 
    kwrds.update({'stream': buffer}) 
    pp_pprint(object, **kwrds) 
    words = buffer.getvalue().split() 
    buffer.close() 

    # word wrap output onto multiple lines <= width characters 
    try: 
     print >> stream, textwrap.fill(' '.join(words), width=width) 
    except TypeError: # Python 3 
     print(textwrap.fill(' '.join(words), width=width), file=stream) 

d = dict((('john',1), ('paul',2), ('mary',3))) 
od = OrderedDict((('john',1), ('paul',2), ('mary',3))) 
lod = [OrderedDict((('john',1), ('paul',2), ('mary',3))), 
     OrderedDict((('moe',1), ('curly',2), ('larry',3))), 
     OrderedDict((('weapons',1), ('mass',2), ('destruction',3)))] 

输出示例:

pprint(d, width=40) 

»      {'john': 1, 'mary': 3, 'paul': 2}

pprint(od, width=40) 

»  OrderedDict([('john', 1), ('paul', 2),
      ('mary', 3)])

pprint(lod, width=40) 

»  [OrderedDict([('john', 1), ('paul', 2),
      ('mary', 3)]), OrderedDict([('moe', 1),
      ('curly', 2), ('larry', 3)]),
      OrderedDict([('weapons', 1), ('mass',
      2), ('destruction', 3)])]

104

作为临时解决方法,您可以尝试以JSON格式进行转储。 你失去了一些类型的信息,但它看起来不错,并保持秩序。

import json 

pprint(data, indent=4) 
# ^ugly 

print(json.dumps(data, indent=4)) 
# ^nice 
1

pprint()方法只是调用的东西__repr__()方法在里面,OrderedDict似乎没有做太多在它的方法(或不具有一个或某事)。

这里是一个廉价的解决方案,应该工作如果你不关心排列顺序为可见的PPRINT输出,这可能是一个很大的,如果:

class PrintableOrderedDict(OrderedDict): 
    def __repr__(self): 
     return dict.__repr__(self) 

实际上,我惊讶的是,订单没有保存好啊。

0

如果字典项都是一个类型的,你可以用惊人的数据处理库pandas

>>> import pandas as pd 
>>> x = {'foo':1, 'bar':2} 
>>> pd.Series(x) 
bar 2 
foo 1 
dtype: int64 

>>> import pandas as pd 
>>> x = {'foo':'bar', 'baz':'bam'} 
>>> pd.Series(x) 
baz bam 
foo bar 
dtype: object 
2

这是相当粗糙的,但我只是需要一个方式来可视化由任意映射和Iterables组成的数据结构,这就是我在放弃之前想出的。它是递归的,所以它将会通过嵌套结构和列表来处理。我使用集合中的Mapping和Iterable抽象基类来处理任何事情。

我的目标是几乎像yaml一样用简洁的python代码输出,但并没有完全实现。

def format_structure(d, level=0): 
    x = "" 
    if isinstance(d, Mapping): 
     lenk = max(map(lambda x: len(str(x)), d.keys())) 
     for k, v in d.items(): 
      key_text = "\n" + " "*level + " "*(lenk - len(str(k))) + str(k) 
      x += key_text + ": " + format_structure(v, level=level+lenk) 
    elif isinstance(d, Iterable) and not isinstance(d, basestring): 
     for e in d: 
      x += "\n" + " "*level + "- " + format_structure(e, level=level+4) 
    else: 
     x = str(d) 
    return x 

,并使用OrderedDict和OrderedDicts的列出了一些测试数据...(啧Python的需要OrderedDict文字SOOO不好...)

d = OrderedDict([("main", 
        OrderedDict([("window", 
           OrderedDict([("size", [500, 500]), 
              ("position", [100, 900])])), 
           ("splash_enabled", True), 
           ("theme", "Dark")])), 
       ("updates", 
        OrderedDict([("automatic", True), 
           ("servers", 
           [OrderedDict([("url", "http://server1.com"), 
               ("name", "Stable")]), 
           OrderedDict([("url", "http://server2.com"), 
               ("name", "Beta")]), 
           OrderedDict([("url", "http://server3.com"), 
               ("name", "Dev")])]), 
           ("prompt_restart", True)])), 
       ("logging", 
        OrderedDict([("enabled", True), 
           ("rotate", True)]))]) 

print format_structure(d) 

产生以下的输出:

main: 
       window: 
         size: 
          - 500 
          - 500 
        position: 
          - 100 
          - 900 
     splash_enabled: True 
       theme: Dark 
updates: 
      automatic: True 
       servers: 
        - 
          url: http://server1.com 
         name: Stable 
        - 
          url: http://server2.com 
         name: Beta 
        - 
          url: http://server3.com 
         name: Dev 
     prompt_restart: True 
logging: 
     enabled: True 
     rotate: True 

我一起使用以便更好地对齐str.format()的方法的一些想法,但是不喜欢挖进去。您需要动态指定字段宽度,具体取决于您想要的对齐类型,这会变得棘手或麻烦。

无论如何,这表明我的数据以可读的层次结构方式显示,因此适用于我!

7

要打印有序的字典,例如

from collections import OrderedDict 

d=OrderedDict([ 
    ('a', OrderedDict([ 
     ('a1',1), 
     ('a2','sss') 
    ])), 
    ('b', OrderedDict([ 
     ('b1', OrderedDict([ 
      ('bb1',1), 
      ('bb2',4.5)])), 
     ('b2',4.5) 
    ])), 
]) 

我做

def dict_or_OrdDict_to_formatted_str(OD, mode='dict', s="", indent=' '*4, level=0): 
    def is_number(s): 
     try: 
      float(s) 
      return True 
     except ValueError: 
      return False 
    def fstr(s): 
     return s if is_number(s) else '"%s"'%s 
    if mode != 'dict': 
     kv_tpl = '("%s", %s)' 
     ST = 'OrderedDict([\n'; END = '])' 
    else: 
     kv_tpl = '"%s": %s' 
     ST = '{\n'; END = '}' 
    for i,k in enumerate(OD.keys()): 
     if type(OD[k]) in [dict, OrderedDict]: 
      level += 1 
      s += (level-1)*indent+kv_tpl%(k,ST+dict_or_OrdDict_to_formatted_str(OD[k], mode=mode, indent=indent, level=level)+(level-1)*indent+END) 
      level -= 1 
     else: 
      s += level*indent+kv_tpl%(k,fstr(OD[k])) 
     if i!=len(OD)-1: 
      s += "," 
     s += "\n" 
    return s 

print dict_or_OrdDict_to_formatted_str(d) 

其中产量

"a": { 
    "a1": 1, 
    "a2": "sss" 
}, 
"b": { 
    "b1": { 
     "bb1": 1, 
     "bb2": 4.5 
    }, 
    "b2": 4.5 
} 

print dict_or_OrdDict_to_formatted_str(d, mode='OD') 

这将产生

("a", OrderedDict([ 
    ("a1", 1), 
    ("a2", "sss") 
])), 
("b", OrderedDict([ 
    ("b1", OrderedDict([ 
     ("bb1", 1), 
     ("bb2", 4.5) 
    ])), 
    ("b2", 4.5) 
])) 
4

这是一种破解pprint实施的方法。 pprint在打印之前对键进行排序,所以为了保持顺序,我们只需要按照我们想要的方式排序键。

请注意,这会影响items()函数。 因此,您可能想要在执行pprint后保留并恢复重写的函数。

from collections import OrderedDict 
import pprint 

class ItemKey(object): 
    def __init__(self, name, position): 
    self.name = name 
    self.position = position 
    def __cmp__(self, b): 
    assert isinstance(b, ItemKey) 
    return cmp(self.position, b.position) 
    def __repr__(self): 
    return repr(self.name) 

OrderedDict.items = lambda self: [ 
    (ItemKey(name, i), value) 
    for i, (name, value) in enumerate(self.iteritems())] 
OrderedDict.__repr__ = dict.__repr__ 

a = OrderedDict() 
a[4] = '4' 
a[1] = '1' 
a[2] = '2' 
print pprint.pformat(a) # {4: '4', 1: '1', 2: '2'} 
-1

您也可以使用这种简化的kzh答案:

pprint(data.items(), indent=4) 

它保留了订单,将输出几乎比webwurst答案(打印通过JSON倾倒)相同。