Any way to properly pretty-print OrderedDict?

Ever since Python 3.7, Python guarantees that keys in a dictionary will retain their insertion order. (They still don't behave exactly the same as OrderedDict objects, though, as two dicts a and b can be considered equal a == b even if the order of the keys is different, whereas OrderedDict does check this upon testing for equality.)

Python 3.8 or newer:

You can use sort_dicts=False to prevent it from sorting them alphabetically:

>>> example_dict = {'x': 1, 'b': 2, 'm': 3}
>>> import pprint
>>> pprint.pprint(example_dict, sort_dicts=False)
{'x': 1, 'b': 2, 'm': 3}

Python 3.7 or older:

As a temporary workaround, you can try dumping in JSON format instead of using pprint.

You lose some type information, but it looks nice and keeps the order.

>>> import json
>>> print(json.dumps(example_dict, indent=4))
{
    "x": 1,
    "b": 2,
    "m": 3
}

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

>>> from collections import OrderedDict
>>> o = OrderedDict([("aaaaa", 1), ("bbbbbb", 2), ("ccccccc", 3), ("dddddd", 4), ("eeeeee", 5), ("ffffff", 6), ("ggggggg", 7)])
>>> import pprint
>>> pprint.pprint(dict(o.items()))
{'aaaaa': 1,
 'bbbbbb': 2,
 'ccccccc': 3,
 'dddddd': 4,
 'eeeeee': 5,
 'ffffff': 6,
 'ggggggg': 7}

Ever since Python 3.7, Python guarantees that keys in a dictionary will retain their insertion order. So if you are using Python 3.7+, you don't need to make sure that your OrderedDict is alphabetically sorted.


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