标签归档:pprint

有什么方法可以正确打印订购的字典吗?

问题:有什么方法可以正确打印订购的字典吗?

我喜欢Python中的pprint模块。我经常使用它进行测试和调试。我经常使用width选项来确保输出完全适合我的终端窗口。

直到他们在Python 2.7中添加了新的有序词典类型(我真的很喜欢的另一个很酷的功能)之前,它一直运行良好。如果我尝试漂亮地打印有序词典,则显示效果会不好。整个事情并没有出现在每个键值对各自的行上,而是整条显示在一条长行上,该行包装许多次并且很难阅读。

这里有没有人像老旧的无序词典一样,能够很好地打印出来?如果我花了足够的时间,我可能可以使用PrettyPrinter.format方法解决问题,但是我想知道这里是否有人知道解决方案。

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

I like the pprint module in Python. I use it a lot for testing and debugging. I frequently use the width option to make sure the output fits nicely within my terminal window.

It has worked fine until they added the new ordered dictionary type in Python 2.7 (another cool feature I really like). If I try to pretty-print an ordered dictionary, it doesn’t show nicely. Instead of having each key-value pair on its own line, the whole thing shows up on one long line, which wraps many times and is hard to read.

Does anyone here have a way to make it print nicely, like the old unordered dictionaries? I could probably figure something out, possibly using the PrettyPrinter.format method, if I spend enough time, but I am wondering if anyone here already knows of a solution.

UPDATE: I filed a bug report for this. You can see it at http://bugs.python.org/issue10592.


回答 0

作为临时的解决方法,您可以尝试以JSON格式进行转储。您会丢失一些类型信息,但是看起来不错,可以保持顺序。

import json

pprint(data, indent=4)
# ^ugly

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

As a temporary workaround you can try dumping in JSON format. You lose some type information, but it looks nice and keeps the order.

import json

pprint(data, indent=4)
# ^ugly

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

回答 1

如果您的OrderedDict的顺序是alpha排序,则以下内容将起作用,因为pprint将在打印之前对字典进行排序。

pprint(dict(o.items()))

The following will work if the order of your OrderedDict is an alpha sort, since pprint will sort a dict before print.

pprint(dict(o.items()))

回答 2

这是另一个在pprint()内部覆盖并使用stock 函数的方法。与我之前的版本不同,它将OrderedDict在另一个容器(例如a)内处理,list并且还应该能够处理给定的任何可选关键字参数-但是,它对输出的控制程度与另一个容器不同。

它通过将stock函数的输出重定向到一个临时缓冲区中进行操作,然后对其进行自动换行,然后再将其发送到输出流。尽管最终产生的输出不是特别漂亮,但它是不错的,并且可能“足够好”用作解决方法。

更新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)])]

Here’s another answer that works by overriding and using the stock pprint() function internally. Unlike my earlier one it will handle OrderedDict‘s inside another container such as a list and should also be able to handle any optional keyword arguments given — however it does not have the same degree of control over the output that the other one afforded.

It operates by redirecting the stock function’s output into a temporary buffer and then word wraps that before sending it on to the output stream. While the final output produced isn’t exceptionalily pretty, it’s decent and may be “good enough” to use as a workaround.

Update 2.0

Simplified by using standard library textwrap module, and modified to work in both 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)))]

Sample output:

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)])]


回答 3

打印命令字典,例如

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)

哪个Yield

"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)
]))

To print an ordered dict, e.g.

from collections import OrderedDict

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

I do

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)

Which yields

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

or

print dict_or_OrdDict_to_formatted_str(d, mode='OD')

which yields

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

回答 4

这是破解的实现的方法pprintpprint在打印之前对键进行排序,因此,为了保持顺序,我们只需要按所需的方式对键进行排序即可。

请注意,这会影响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'}

Here’s a way that hacks the implementation of pprint. pprint sorts the keys before printing, so to preserve order, we just have to make the keys sort in the way we want.

Note that this impacts the items() function. So you might want to preserve and restore the overridden functions after doing the 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'}

回答 5

这是我漂亮打印OrderedDict的方法

from collections import OrderedDict
import json
d = OrderedDict()
d['duck'] = 'alive'
d['parrot'] = 'dead'
d['penguin'] = 'exploded'
d['Falcon'] = 'discharged'
print(d)
print(json.dumps(d,indent=4))

OutPut:

OrderedDict([('duck', 'alive'), ('parrot', 'dead'), ('penguin', 'exploded'), ('Falcon', 'discharged')])

{
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded",
    "Falcon": "discharged"
}

如果您想按键顺序漂亮地打印字典

print(json.dumps(indent=4,sort_keys=True))
{
    "Falcon": "discharged",
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded"
}

Here is my approach to pretty print an OrderedDict

from collections import OrderedDict
import json
d = OrderedDict()
d['duck'] = 'alive'
d['parrot'] = 'dead'
d['penguin'] = 'exploded'
d['Falcon'] = 'discharged'
print(d)
print(json.dumps(d,indent=4))

OutPut:

OrderedDict([('duck', 'alive'), ('parrot', 'dead'), ('penguin', 'exploded'), ('Falcon', 'discharged')])

{
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded",
    "Falcon": "discharged"
}

If you want to pretty print dictionary with keys in sorted order

print(json.dumps(indent=4,sort_keys=True))
{
    "Falcon": "discharged",
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded"
}

回答 6

这非常粗糙,但是我只需要一种可视化由任意映射和Iterable组成的数据结构的方法,这就是我放弃之前想到的。它是递归的,因此它将遍历嵌套结构和列表。我使用了集合中的Mapping和Iterable抽象基类来处理几乎所有内容。

我的目标是使用简洁的python代码输出几乎像yaml这样的输出,但并没有完全做到这一点。

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的列表…(sheesh Python严重需要OrderedDict文字…)

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()进行更好的对齐的过程中,我有一些想法,但并不想深入研究它。您需要根据所需的对齐类型动态指定字段宽度,这会变得棘手或麻烦。

无论如何,这以可读的分层方式向我显示了我的数据,因此对我有用!

This is pretty crude, but I just needed a way to visualize a data structure made up of any arbitrary Mappings and Iterables and this is what I came up with before giving up. It’s recursive, so it will fall through nested structures and lists just fine. I used the Mapping and Iterable abstract base classes from collections to handle just about anything.

I was aiming for almost yaml like output with concise python code, but didn’t quite make it.

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

and some test data using OrderedDict and lists of OrderedDicts… (sheesh Python needs OrderedDict literals sooo badly…)

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)

yields the following output:

   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

I had some thoughts along the way of using str.format() for better alignment, but didn’t feel like digging into it. You’d need to dynamically specify the field widths depending on the type of alignment you want, which would get either tricky or cumbersome.

Anyway, this shows me my data in readable hierarchical fashion, so that works for me!


回答 7

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)
def pprint_od(od):
    print "{"
    for key in od:
        print "%s:%s,\n" % (key, od[key]) # Fixed syntax
    print "}"

There you go ^^

for item in li:
    pprint_od(item)

or

(pprint_od(item) for item in li)

回答 8

我已经在python3.5上测试了这个基于Monkey补丁的邪恶方法,它可以工作:

pprint.PrettyPrinter._dispatch[pprint._collections.OrderedDict.__repr__] = pprint.PrettyPrinter._pprint_dict


def unsorted_pprint(data):
    def fake_sort(*args, **kwargs):
        return args[0]
    orig_sorted = __builtins__.sorted
    try:
        __builtins__.sorted = fake_sort
        pprint.pprint(data)
    finally:
        __builtins__.sorted = orig_sorted

您可以pprint使用通常的基于dict的摘要,还可以在通话过程中禁用排序功能,这样就不会为打印实际排序任何键。

I’ve tested this unholy monkey-patch based hack on python3.5 and it works:

pprint.PrettyPrinter._dispatch[pprint._collections.OrderedDict.__repr__] = pprint.PrettyPrinter._pprint_dict


def unsorted_pprint(data):
    def fake_sort(*args, **kwargs):
        return args[0]
    orig_sorted = __builtins__.sorted
    try:
        __builtins__.sorted = fake_sort
        pprint.pprint(data)
    finally:
        __builtins__.sorted = orig_sorted

You make pprint use the usual dict based summary and also disable sorting for the duration of the call so that no keys are actually sorted for printing.


回答 9

从Python 3.8开始:pprint.PrettyPrinter公开sort_dicts关键字参数。

默认情况下为True,将其设置为False将使字典不排序。

>>> from pprint import PrettyPrinter

>>> x = {'John': 1,
>>>      'Mary': 2,
>>>      'Paul': 3,
>>>      'Lisa': 4,
>>>      }

>>> PrettyPrinter(sort_dicts=False).pprint(x)

将输出:

{'John': 1, 
 'Mary': 2, 
 'Paul': 3,
 'Lisa': 4}

参考:https : //docs.python.org/3/library/pprint.html

As of Python 3.8 : pprint.PrettyPrinter exposes the sort_dicts keyword parameter.

True by default, setting it to False will leave the dictionary unsorted.

>>> from pprint import PrettyPrinter

>>> x = {'John': 1,
>>>      'Mary': 2,
>>>      'Paul': 3,
>>>      'Lisa': 4,
>>>      }

>>> PrettyPrinter(sort_dicts=False).pprint(x)

Will output :

{'John': 1, 
 'Mary': 2, 
 'Paul': 3,
 'Lisa': 4}

Reference : https://docs.python.org/3/library/pprint.html


回答 10

pprint()方法只是调用其中__repr__()的事物的方法,在它的方法中OrderedDict似乎并没有做很多(或没有任何东西)。

如果您不关心订单在打印输出中的可见性,那么这是一个便宜的解决方案,该解决方案在以下情况下可能会很大:

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

令我惊讶的是,订单没有得到保存……嗯。

The pprint() method is just invoking the __repr__() method of things in it, and OrderedDict doesn’t appear to do much in it’s method (or doesn’t have one or something).

Here’s a cheap solution that should work IF YOU DON’T CARE ABOUT THE ORDER BEING VISIBLE IN THE PPRINT OUTPUT, which may be a big if:

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

I’m actually surprised that the order isn’t preserved… ah well.


回答 11

您还可以使用以下简化的kzh答案:

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

它保留顺序,并且输出结果几乎与webwurst答案相同(通过json dump打印)。

You can also use this simplification of the kzh answer:

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

It preserves the order and will output almost the same than the webwurst answer (print through json dump).


回答 12

对于python <3.8(例如3.6):

Monkey补丁pprintsorted为了防止其排序。这也将有利于一切递归工作,并且比json需要使用width参数的用户更适合:

import pprint
pprint.sorted = lambda arg, *a, **kw: arg

>>> pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)
{'z': 1,
 'a': 2,
 'c': {'z': 0,
       'a': 1}}

编辑:清理

要清理这个肮脏的业务,只需运行: pprint.sorted = sorted

对于真正干净的解决方案,甚至可以使用contextmanager:

import pprint
import contextlib

@contextlib.contextmanager
def pprint_ordered():
    pprint.sorted = lambda arg, *args, **kwargs: arg
    yield
    pprint.sorted = sorted

# usage:

with pprint_ordered():
    pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)

# without it    
pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)

# prints: 
#    
# {'z': 1,
#  'a': 2,
#  'c': {'z': 0,
#        'a': 1}}
#
# {'a': 2,
#  'c': {'a': 1,
#        'z': 0},
#  'z': 1}

For python < 3.8 (e.g. 3.6):

Monkey patch pprint‘s sorted in order to prevent it from sorting. This will have the benefit of everything working recursively as well, and is more suitable than the json option for whoever needs to use e.g. width parameter:

import pprint
pprint.sorted = lambda arg, *a, **kw: arg

>>> pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)
{'z': 1,
 'a': 2,
 'c': {'z': 0,
       'a': 1}}

Edit: cleaning up

To clean up after this dirty business just run: pprint.sorted = sorted

For a really clean solution can even use a contextmanager:

import pprint
import contextlib

@contextlib.contextmanager
def pprint_ordered():
    pprint.sorted = lambda arg, *args, **kwargs: arg
    yield
    pprint.sorted = sorted

# usage:

with pprint_ordered():
    pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)

# without it    
pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)

# prints: 
#    
# {'z': 1,
#  'a': 2,
#  'c': {'z': 0,
#        'a': 1}}
#
# {'a': 2,
#  'c': {'a': 1,
#        'z': 0},
#  'z': 1}

回答 13

您可以重新定义pprint()并拦截对的调用OrderedDict。这是一个简单的例子。按照规定,OrderedDict越权代码忽略任何可选streamindentwidth,或者depth可能已经通过关键字,但可以增强贯彻落实。但这种方法不处理他们另一个容器内,比如一个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
# }

You could redefine pprint() and intercept calls for OrderedDict‘s. Here’s a simple illustration. As written, the OrderedDict override code ignores any optional stream, indent, width, or depth keywords that may have been passed, but could be enhanced to implement them. Unfortunately this technique doesn’t handle them inside another container, such as a list of OrderDict‘s

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
# }

回答 14

如果字典项都是一种类型,则可以使用令人惊叹的数据处理库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

If the dictionary items are all of one type, you could use the amazing data-handling library pandas:

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

or

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

使用日志记录打印pprint的输出

问题:使用日志记录打印pprint的输出

我想使用pprint的输出来显示复杂的数据结构,但是我想使用日志记录模块而不是stdout来输出它。

ds = [{'hello': 'there'}]
logging.debug( pprint.pprint(ds) ) # outputs as STDOUT

I want to use pprint’s output to show a complex data structure, but I would like to output it using the logging module rather than stdout.

ds = [{'hello': 'there'}]
logging.debug( pprint.pprint(ds) ) # outputs as STDOUT

回答 0

使用pprint.pformat得到一个字符串,然后将其发送到您的日志框架。

from pprint import pformat
ds = [{'hello': 'there'}]
logging.debug(pformat(ds))

Use pprint.pformat to get a string, and then send it to your logging framework.

from pprint import pformat
ds = [{'hello': 'there'}]
logging.debug(pformat(ds))

回答 1

上述解决方案没有相当,因为我还使用格式化的时候记录添加名称和levelname削减对我来说。看起来有点不整洁:

__main__    : DEBUG   : ['aaaaaaaaaaaaaaaaaaaa',
'bbbbbbbbbbbbbbbbbbbb',
'cccccccccccccccccccc',
'dddddddddddddddddddd']
__main__    : DEBUG   : Some other logging text

可能有一个更优雅的解决方案,但这是:

for line in pprint.pformat(ds).split('\n'):
    logging.debug(line)

产生更好的东西:

__main__    : DEBUG   : ['aaaaaaaaaaaaaaaaaaaa',
__main__    : DEBUG   :  'bbbbbbbbbbbbbbbbbbbb',
__main__    : DEBUG   :  'cccccccccccccccccccc',
__main__    : DEBUG   :  'dddddddddddddddddddd']
__main__    : DEBUG   : Some other logging text

The solution above didn’t quite cut it for me because I’m also using a formatter to add name and levelname when logging. It looks a little untidy:

__main__    : DEBUG   : ['aaaaaaaaaaaaaaaaaaaa',
'bbbbbbbbbbbbbbbbbbbb',
'cccccccccccccccccccc',
'dddddddddddddddddddd']
__main__    : DEBUG   : Some other logging text

There may be a more elegant solution, but this:

for line in pprint.pformat(ds).split('\n'):
    logging.debug(line)

produces something a little nicer:

__main__    : DEBUG   : ['aaaaaaaaaaaaaaaaaaaa',
__main__    : DEBUG   :  'bbbbbbbbbbbbbbbbbbbb',
__main__    : DEBUG   :  'cccccccccccccccccccc',
__main__    : DEBUG   :  'dddddddddddddddddddd']
__main__    : DEBUG   : Some other logging text