Can I avoid a sorted dictionary output after I've used pprint.pprint, in Python?

Since Python 3.7 (or 3.6 in the case of cPython), dict preserves insertion order. For any version prior, you will need to use an OrderedDict to keep keys in order.

Although, from the doc on pprint:

Dictionaries are sorted by key before the display is computed.

This means pprint will break your desired order regardless.

Use json.dumps

While it is possible to subclass pprint.PrettyPrinter not to sort keys before displaying, it is tedious and a good alternative is to use json.dumps to pretty print your data.

Code

import json
from collections import OrderedDict

# For Python 3.6 and prior, use an OrderedDict
d = OrderedDict(b="Maria", c="Helen", a="George")

print(json.dumps(d, indent=1))

Output

{
 "b": "Maria",
 "c": "Helen",
 "a": "George"
}

If you read the source of pprint.py you'll find that in PrettyPrinter._pprint_dict(), the method responsible for formatting dicts:

def _pprint_dict(self, object, stream, indent, allowance, context, level):
    write = stream.write
    write('{')
    if self._indent_per_level > 1:
        write((self._indent_per_level - 1) * ' ')
    length = len(object)
    if length:
        items = sorted(object.items(), key=_safe_tuple)
        self._format_dict_items(items, stream, indent, allowance + 1,
                                context, level)
    write('}')

_dispatch[dict.__repr__] = _pprint_dict

There's this line items = sorted(object.items(), key=_safe_tuple), so dict items are always sorted first before being processed for formatting, and you will have to override it yourself by copying and pasting it and removing the offending line in your own script:

import pprint as pp
def _pprint_dict(self, object, stream, indent, allowance, context, level):
    write = stream.write
    write('{')
    if self._indent_per_level > 1:
        write((self._indent_per_level - 1) * ' ')
    length = len(object)
    if length:
        self._format_dict_items(object.items(), stream, indent, allowance + 1,
                                context, level)
    write('}')
pp.PrettyPrinter._dispatch[dict.__repr__] = _pprint_dict

so that:

pp.pprint({"b" : "Maria", "c" : "Helen", "a" : "George"}, width=1)

will output (in Python 3.6+):

{'b': 'Maria',
 'c': 'Helen',
 'a': 'George'}

A more generic solution is to use unittest.mock.patch to override the built-in sorted function with a function that does nothing but return the given first argument:

import pprint
from unittest.mock import patch

def unsorted_pprint(*args, **kwargs):
    with patch('builtins.sorted', new=lambda l, **_: l):
        orig_pprint(*args, **kwargs)

orig_pprint = pprint.pprint
pprint.pprint = unsorted_pprint

so that:

pprint.pprint({"b" : "Maria", "c" : "Helen", "a" : "George"})

outputs:

{'b': 'Maria', 'c': 'Helen', 'a': 'George'}