Python pprint — Core Concepts

What pprint provides

The pprint module formats Python data structures for human readability. It handles dicts, lists, tuples, sets, and nested combinations — the structures you stare at most during debugging.

Basic usage

from pprint import pprint

data = {"users": [{"name": "Alice", "roles": ["admin", "editor"]}, {"name": "Bob", "roles": ["viewer"]}], "count": 2}

pprint(data)

Output:

{'count': 2,
 'users': [{'name': 'Alice', 'roles': ['admin', 'editor']},
           {'name': 'Bob', 'roles': ['viewer']}]}

Compare this with print(data), which dumps everything on one line.

Key parameters

width (default: 80)

Controls the maximum line width before pprint breaks to the next line:

pprint(data, width=40)  # narrower, more line breaks
pprint(data, width=200) # wider, fewer line breaks

If the entire structure fits within width, pprint keeps it on one line — it only expands when needed.

depth

Limits how deep into nested structures pprint will go. Deeper levels show as ...:

pprint(data, depth=1)
# {'count': 2, 'users': [...]}

Useful when you have deeply nested data and only care about the top level.

sort_dicts (Python 3.8+)

By default, pprint sorts dictionary keys alphabetically. Set sort_dicts=False to preserve insertion order:

pprint(data, sort_dicts=False)

compact (Python 3.3+)

When True, pprint tries to fit as many items as possible on each line (within width) instead of putting each on its own line:

pprint(list(range(20)), compact=True, width=40)

underscore_numbers (Python 3.10+)

Adds underscores to large numbers for readability:

pprint({"population": 8045311447}, underscore_numbers=True)
# {'population': 8_045_311_447}

PrettyPrinter class

For repeated use with the same settings, create an instance:

from pprint import PrettyPrinter

pp = PrettyPrinter(width=60, depth=3, sort_dicts=False)
pp.pprint(data)

# Get formatted string without printing
formatted = pp.pformat(data)

The pformat method returns the formatted string instead of printing it — useful for logging or writing to files.

pprint vs. json.dumps

Both can format nested data, but they serve different audiences:

Featurepprintjson.dumps(indent=2)
Python-native types✅ sets, tuples, custom objects❌ JSON types only
Valid Python syntax✅ output is eval-able❌ JSON syntax
Valid JSON output
Depth limiting
Handles circular refs✅ (shows <Recursion...>)❌ (raises error)

Use pprint for debugging Python objects. Use json.dumps when you need actual JSON output.

Common misconception

pprint is sometimes mistaken for a serialization tool. It’s not — it’s a display tool. The output looks like Python code, but it’s not guaranteed to be valid Python in all cases (especially with custom objects). For serialization, use json, pickle, or similar.

One thing to remember

pprint shines during debugging and exploration. Reach for it whenever print() produces an unreadable wall of text, and remember pformat() when you need the string rather than stdout output.

pythonstandard-librarydebugging

See Also

  • Python Atexit How Python's atexit module lets your program clean up after itself right before it shuts down.
  • Python Bisect Sorted Lists How Python's bisect module finds things in sorted lists the way you'd find a word in a dictionary — by jumping to the middle.
  • Python Contextlib How Python's contextlib module makes the 'with' statement work for anything, not just files.
  • Python Copy Module Why copying data in Python isn't as simple as it sounds, and how the copy module prevents sneaky bugs.
  • Python Dataclass Field Metadata How Python dataclass fields can carry hidden notes — like sticky notes on a filing cabinet that tools read automatically.