I have big dictionary which I`m printing for viewing with prettyprint, but how I can keep formatting but kill sorting mechanism in pprint?
6 Answers
Python 3.8 or newer:
Use sort_dicts=False
:
pprint.pprint(data, sort_dicts=False)
Python 3.7 or older:
You can monkey patch the pprint module.
import pprint
pprint.pprint({"def":2,"ghi":3,"abc":1,})
pprint._sorted = lambda x:x
# Or, for Python 3.7:
# pprint.sorted = lambda x, key=None: x
pprint.pprint({"def":2,"ghi":3, "abc":1})
Since the 2nd output is essentiallly randomly sorted, your output may be different from mine:
{'abc': 1, 'def': 2, 'ghi': 3}
{'abc': 1, 'ghi': 3, 'def': 2}
Another version that is more complex, but easier to use:
import pprint
import contextlib
@contextlib.contextmanager
def pprint_nosort():
# Note: the pprint implementation changed somewhere
# between 2.7.12 and 3.7.0. This is the danger of
# monkeypatching!
try:
# Old pprint
orig,pprint._sorted = pprint._sorted, lambda x:x
except AttributeError:
# New pprint
import builtins
orig,pprint.sorted = None, lambda x, key=None:x
try:
yield
finally:
if orig:
pprint._sorted = orig
else:
del pprint.sorted
# For times when you don't want sorted output
with pprint_nosort():
pprint.pprint({"def":2,"ghi":3, "abc":1})
# For times when you do want sorted output
pprint.pprint({"def":2,"ghi":3, "abc":1})

- 7,332
- 3
- 48
- 69

- 163,533
- 20
- 239
- 308
-
1This no longer works unfortunately, `pprint` uses the `sorted` built-in everywhere – RunOrVeith Dec 14 '18 at 16:12
-
3Thanks, @RunOrVeith - I've updated the answer to include support for, at the least, 3.7.0. – Robᵩ Dec 29 '18 at 14:39
-
`key=None` y assigning? – Smart Manoj Jun 26 '19 at 09:47
-
@SmartManoj - that's not an assignment, it is a default value of the `key` parameter in that lambda. I don't recall anymore why that parameter has a default value. – Robᵩ Jun 28 '19 at 17:21
-
I think the default value is not needed – Smart Manoj Jun 29 '19 at 09:33
-
I think the default value is not needed – Smart Manoj Jun 29 '19 at 09:34
-
Does not work for nested dicts – John Glen Mar 18 '23 at 19:38
As of Python 3.8, you can finally disable this using sort_dicts=False
. Note that dictionaries are insertion-ordered since Python 3.7 (and in practice, even since 3.6).
import pprint
data = {'not': 'sorted', 'awesome': 'dict', 'z': 3, 'y': 2, 'x': 1}
pprint.pprint(data, sort_dicts=False)
# prints {'not': 'sorted', 'awesome': 'dict', 'z': 3, 'y': 2, 'x': 1}
Alternatively, create a pretty printer object:
pp = pprint.PrettyPrinter(sort_dicts=False)
pp.pprint(data)
This does not affect sets (which are still sorted), but then sets do not have insertion-ordering guarantees.
-
Does not work with nested dicts. The order of the nested dicts is printed out of order. – John Glen Mar 18 '23 at 19:35
Instead of pprint.pprint
, save yourself 4 characters and use pprint.pp
, which doesn't sort:
pprint.pp(object, *args, sort_dicts=False, **kwargs)
Prints the formatted representation of object followed by a newline. If sort_dicts is false (the default), dictionaries will be displayed with their keys in insertion order, otherwise the dict keys will be sorted.
args
andkwargs
will be passed topprint()
as formatting parameters.New in version 3.8.

- 338,267
- 99
- 616
- 750
You can subclass PrettyPrinter
and remove the sorted(object.items())
from _pprint_dict
.
NOTE: this code is Python 3.5+
# unsorted_pprint.py
from pprint import PrettyPrinter, _builtin_scalars, _recursion
__all__ = [
'UnsortedPrettyPrinter',
'pprint2',
'pformat2',
]
class UnsortedPrettyPrinter(PrettyPrinter):
"""Pretty printer that retains original dict ordering
"""
def __init__(self, *args, **kwargs):
super().__init__()
self._dispatch = {
**self._dispatch,
dict.__repr__: self._pprint_dict,
}
@staticmethod
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 = object.items()
self._format_dict_items(items, stream, indent, allowance + 1,
context, level)
write('}')
def format(self, object, context, maxlevels, level):
"""Format object for a specific context, returning a string
and flags indicating whether the representation is 'readable'
and whether the object represents a recursive construct.
"""
return self._safe_repr(object, context, maxlevels, level)
def _safe_repr(self, object, context, maxlevels, level):
typ = type(object)
if typ in _builtin_scalars:
return repr(object), True, False
r = getattr(typ, "__repr__", None)
if issubclass(typ, dict) and r is dict.__repr__:
if not object:
return "{}", True, False
objid = id(object)
if maxlevels and level >= maxlevels:
return "{...}", False, objid in context
if objid in context:
return _recursion(object), False, True
context[objid] = 1
readable = True
recursive = False
components = []
append = components.append
level += 1
saferepr = self._safe_repr
items = object.items()
for k, v in items:
krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
append("%s: %s" % (krepr, vrepr))
readable = readable and kreadable and vreadable
if krecur or vrecur:
recursive = True
del context[objid]
return "{%s}" % ", ".join(components), readable, recursive
if (issubclass(typ, list) and r is list.__repr__) or \
(issubclass(typ, tuple) and r is tuple.__repr__):
if issubclass(typ, list):
if not object:
return "[]", True, False
format = "[%s]"
elif len(object) == 1:
format = "(%s,)"
else:
if not object:
return "()", True, False
format = "(%s)"
objid = id(object)
if maxlevels and level >= maxlevels:
return format % "...", False, objid in context
if objid in context:
return _recursion(object), False, True
context[objid] = 1
readable = True
recursive = False
components = []
append = components.append
level += 1
for o in object:
orepr, oreadable, orecur = self._safe_repr(o, context, maxlevels, level)
append(orepr)
if not oreadable:
readable = False
if orecur:
recursive = True
del context[objid]
return format % ", ".join(components), readable, recursive
rep = repr(object)
return rep, (rep and not rep.startswith('<')), False
def pprint2(object, stream=None, indent=1, width=80, depth=None, *,
compact=False):
"""Pretty-print a Python object to a stream [default is sys.stdout].
dict items are left unsorted.
"""
printer = UnsortedPrettyPrinter(
stream=stream,
indent=indent,
width=width,
depth=depth,
compact=compact,
)
printer.pprint(object)
def pformat2(object, indent=1, width=80, depth=None, *, compact=False):
"""Format a Python object into a pretty-printed representation.
dict items are left unsorted.
"""
return UnsortedPrettyPrinter(
indent=indent,
width=width,
depth=depth,
compact=compact,
).pformat(object)

- 5,230
- 4
- 34
- 59

- 5,572
- 2
- 32
- 38
I know that I am a bit late here but my preferred way to disable sorting dicts is by using partial
:
from functools import partial
from pprint import pprint
pprint = partial(pprint, sort_dicts=False)
Personally I like this way as it introduces the smallest diffs.
It has the benefit of monkey patching in that you only have to make changes at one spot(unlike other options) without having to mess with the internals of pprint
.
I'm using py3.8 but this should work from whenever sort_dicts
option was added.

- 33
- 1
- 8
You can use json.dumps
with indent=4
. This creates a formatted string, that can be printed nicely and does not sort keys by default.
Note: this works also for old pythons
import json
d = {3:4, 1:2, 5:6}
print(json.dumps(d, indent=4))
output:
{
"3": 4,
"1": 2,
"5": 6
}

- 1,704
- 1
- 18
- 19