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
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
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)
]))
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)
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}}
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}
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
# }
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'}