问题:有什么方法可以正确打印订购的字典吗?
我喜欢Python中的pprint模块。我经常使用它进行测试和调试。我经常使用width选项来确保输出完全适合我的终端窗口。
直到他们在Python 2.7中添加了新的有序词典类型(我真的很喜欢的另一个很酷的功能)之前,它一直运行良好。如果我尝试漂亮地打印有序词典,则显示效果会不好。整个事情并没有出现在每个键值对各自的行上,而是整条显示在一条长行上,该行包装许多次并且很难阅读。
这里有没有人像老旧的无序词典一样,能够很好地打印出来?如果我花了足够的时间,我可能可以使用PrettyPrinter.format方法解决问题,但是我想知道这里是否有人知道解决方案。
更新:我为此提交了一个错误报告。您可以在http://bugs.python.org/issue10592上看到它。
回答 0
作为临时的解决方法,您可以尝试以JSON格式进行转储。您会丢失一些类型信息,但是看起来不错,可以保持顺序。
import json
pprint(data, indent=4)
# ^ugly
print(json.dumps(data, indent=4))
# ^nice
回答 1
如果您的OrderedDict的顺序是alpha排序,则以下内容将起作用,因为pprint将在打印之前对字典进行排序。
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)])]
回答 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)
]))
回答 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'}
回答 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"
}
回答 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()进行更好的对齐的过程中,我有一些想法,但并不想深入研究它。您需要根据所需的对齐类型动态指定字段宽度,这会变得棘手或麻烦。
无论如何,这以可读的分层方式向我显示了我的数据,因此对我有用!
回答 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)
回答 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的摘要,还可以在通话过程中禁用排序功能,这样就不会为打印实际排序任何键。
回答 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}
回答 10
该pprint()
方法只是调用其中__repr__()
的事物的方法,在它的方法中OrderedDict
似乎并没有做很多(或没有任何东西)。
如果您不关心订单在打印输出中的可见性,那么这是一个便宜的解决方案,该解决方案在以下情况下可能会很大:
class PrintableOrderedDict(OrderedDict):
def __repr__(self):
return dict.__repr__(self)
令我惊讶的是,订单没有得到保存……嗯。
回答 11
回答 12
对于python <3.8(例如3.6):
Monkey补丁pprint
是sorted
为了防止其排序。这也将有利于一切递归工作,并且比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}
回答 13
您可以重新定义pprint()
并拦截对的调用OrderedDict
。这是一个简单的例子。按照规定,OrderedDict
越权代码忽略任何可选stream
,indent
,width
,或者depth
可能已经通过关键字,但可以增强贯彻落实。但这种方法不处理他们另一个容器内,比如一个list
的OrderDict
的
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