使用pprint漂亮打印OrderedDicts

时间:2014-01-29 01:17:27

标签: python ordereddictionary pprint

我正在使用pprint来很好地打印dict并且它正常工作。现在,我转而使用模块OrderedDict中的collections。不幸的是,pprint路由似乎并没有意识到这些对象也或多或少dict,并且回退到打印为长行。

>>> d = { i:'*'*i for i in range(8) }
>>> pprint.pprint(d)
{0: '',
 1: '*',
 2: '**',
 3: '***',
 4: '****',
 5: '*****',
 6: '******',
 7: '*******'}
>>> pprint.pprint(collections.OrderedDict(d))
OrderedDict([(0, ''), (1, '*'), (2, '**'), (3, '***'), (4, '****'), (5, '*****'), (6, '******'), (7, '*******')])

是否可以更好地表达OrderedDict s?也许即使它们嵌套 in 正常dictlist

4 个答案:

答案 0 :(得分:3)

我找到了一个相对简单的解决方案,但它包含了使您的有序字典的输出看起来像是常规dict对象的风险。

使用上下文管理器阻止pprint排序字典键的原始解决方案来自this answer

@contextlib.contextmanager
def pprint_OrderedDict():
    pp_orig = pprint._sorted
    od_orig = OrderedDict.__repr__
    try:
        pprint._sorted = lambda x:x
        OrderedDict.__repr__ = dict.__repr__
        yield
    finally:
        pprint._sorted = pp_orig
        OrderedDict.__repr__ = od_orig

(您也可以使用OrderedDict.__repr__修补dict.__repr__方法,但请不要。)

示例:

>>> foo = [('Roger', 'Owner'), ('Diane', 'Manager'), ('Bob', 'Manager'),
...        ('Ian', 'Associate'), ('Bill', 'Associate'), ('Melinda', 'Associate')]

>>> d = OrderedDict(foo)
>>> pprint.pprint(d)
OrderedDict([('Roger', 'Owner'), ('Diane', 'Manager'), ('Bob', 'Manager'), ('Ian', 'Associate'), ('Bill', 'Associate'), ('Melinda', 'Associate')])

>>> pprint.pprint(dict(d))
{'Bill': 'Associate',
 'Bob': 'Manager',
 'Diane': 'Manager',
 'Ian': 'Associate',
 'Melinda': 'Associate',
 'Roger': 'Owner'}

>>> with pprint_OrderedDict():
...     pprint.pprint(d)
...
{'Roger': 'Owner',
 'Diane': 'Manager',
 'Bob': 'Manager',
 'Ian': 'Associate',
 'Bill': 'Associate',
 'Melinda': 'Associate'}

答案 1 :(得分:2)

试试这个:

d = collections.OrderedDict({ i:'*'*i for i in range(8) })

修改

pprint.pprint(list(d.items()))

答案 2 :(得分:1)

如果您专门针对CPython * 3.6或更高版本,那么您可以just use regular dictionaries代替OrderedDict。你会错过几个methods exclusive to OrderedDict,但这并不能保证可以移植到其他Python实现,**但它可能是完成你想要做的最简单的方法。

* CPython是Python的参考实现,可以从python.org下载 ** CPython stole this idea from PyPy,所以你可以依赖它在那里工作。

答案 3 :(得分:0)

我意识到这是一种恶作剧,但我认为我会发布我使用的内容。它的主要优点是它的aoutput可以读回到python中,因此允许例如在表示之间关闭(例如,我在JSON文件上使用它)。当然,它通过从内部_format函数中删除一些代码来打破pprint封装。

#!/bin/env python
from __future__ import print_function

import pprint;
from collections import OrderedDict
import json
import sys


class MyPP (pprint.PrettyPrinter):
    def _format(self, object, stream, indent, allowance, context, level):
        if not isinstance(object, OrderedDict) :
            return pprint.PrettyPrinter._format(self, object, stream, indent, allowance, context, level)
        level = level + 1
        objid = id(object)
        if objid in context:
            stream.write(_recursion(object))
            self._recursive = True
            self._readable = False
            return
        write = stream.write
        _len=len
        rep = self._repr(object, context, level - 1)
        typ = type(object)
        sepLines = _len(rep) > (self._width - 1 - indent - allowance)

        if self._depth and level > self._depth:
            write(rep)
            return

        write('OrderedDict([\n%s'%(' '*(indent+1),))
        if self._indent_per_level > 1:
            write((self._indent_per_level - 1) * ' ')
        length = _len(object)
        #import pdb; pdb.set_trace()
        if length:
            context[objid] = 1
            indent = indent + self._indent_per_level
            items = object.items()
            key, ent = items[0]
            rep = self._repr(key, context, level)
            write('( ')
            write(rep)
            write(', ')
            self._format(ent, stream, indent + _len(rep) + 2,
                         allowance + 1, context, level)
            write(' )')
            if length > 1:
                for key, ent in items[1:]:
                    rep = self._repr(key, context, level)
                    if sepLines:
                        write(',\n%s( %s , ' % (' '*indent, rep))
                    else:
                        write(', ( %s , ' % rep)
                    self._format(ent, stream, indent + _len(rep) + 2,
                                 allowance + 1, context, level)
                    write(' )')

            indent = indent - self._indent_per_level
            del context[objid]
        write('])')
        return

pp = MyPP(indent=1)
handle=open(sys.argv[1],"r")
values=json.loads(handle.read(),object_pairs_hook=OrderedDict)
pp.pprint(values)