The pprint module formats complex data structures for human readability. Essential for debugging nested dicts, lists, and API responses.
Basic pprint
from pprint import pprint
data = {
"users": [
{"name": "Alice", "email": "alice@example.com", "roles": ["admin", "user"]},
{"name": "Bob", "email": "bob@example.com", "roles": ["user"]},
],
"metadata": {"version": "1.0", "generated": "2024-01-15"},
}
# Regular print: hard to read
print(data)
# {'users': [{'name': 'Alice', 'email': 'alice@example.com', 'roles': ['admin', 'user']}, ...
# pprint: formatted
pprint(data)
# {'metadata': {'generated': '2024-01-15', 'version': '1.0'},
# 'users': [{'email': 'alice@example.com',
# 'name': 'Alice',
# 'roles': ['admin', 'user']},
# {'email': 'bob@example.com',
# 'name': 'Bob',
# 'roles': ['user']}]}pformat: Get String Instead of Print
from pprint import pformat
data = {"a": [1, 2, 3], "b": {"nested": True}}
formatted = pformat(data)
# Now you can log it, save it, etc.
print(formatted)Width Control
from pprint import pprint
data = ["item1", "item2", "item3", "item4", "item5"]
# Default width (80)
pprint(data)
# ['item1', 'item2', 'item3', 'item4', 'item5']
# Narrow width forces wrapping
pprint(data, width=30)
# ['item1',
# 'item2',
# 'item3',
# 'item4',
# 'item5']Depth Limits
from pprint import pprint
deep = {"a": {"b": {"c": {"d": {"e": "deep"}}}}}
# Full depth
pprint(deep)
# {'a': {'b': {'c': {'d': {'e': 'deep'}}}}}
# Limited depth
pprint(deep, depth=2)
# {'a': {'b': {...}}}Compact Mode
from pprint import pprint
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Normal: each element on new line if doesn't fit
pprint(data, width=20)
# [1,
# 2,
# 3,
# ...
# Compact: fit as many as possible per line
pprint(data, width=20, compact=True)
# [1, 2, 3, 4, 5,
# 6, 7, 8, 9, 10]Sorting Keys
from pprint import pprint
data = {"zebra": 1, "apple": 2, "mango": 3}
# Default: sorted keys
pprint(data)
# {'apple': 2, 'mango': 3, 'zebra': 1}
# Preserve insertion order (Python 3.8+)
pprint(data, sort_dicts=False)
# {'zebra': 1, 'apple': 2, 'mango': 3}PrettyPrinter Class
For repeated formatting with same settings:
from pprint import PrettyPrinter
pp = PrettyPrinter(
indent=2,
width=60,
depth=3,
compact=True,
sort_dicts=False,
)
pp.pprint(data)
# Get formatted string
formatted = pp.pformat(data)Stream Output
from pprint import pprint
import sys
# Print to stderr
pprint(data, stream=sys.stderr)
# Print to file
with open("debug.txt", "w") as f:
pprint(data, stream=f)Practical Examples
Debug Logger
from pprint import pformat
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
def debug_data(label: str, data):
logger.debug(f"{label}:\n{pformat(data)}")
response = {"status": 200, "data": [1, 2, 3]}
debug_data("API Response", response)API Response Inspection
from pprint import pprint
import requests
def inspect_response(url: str):
response = requests.get(url)
print(f"Status: {response.status_code}")
print("Headers:")
pprint(dict(response.headers), depth=1)
print("Body:")
pprint(response.json(), depth=2)Config File Dump
from pprint import pformat
def save_config(config: dict, path: str):
with open(path, "w") as f:
f.write("# Generated config\n")
f.write(f"config = {pformat(config)}\n")REPL Enhancement
import sys
from pprint import pprint
# Make pprint the default display in REPL
sys.displayhook = lambda x: pprint(x) if x is not None else NoneComparison: print vs pprint vs json.dumps
import json
from pprint import pprint
data = {"key": [1, 2, {"nested": True}]}
# print: single line, no formatting
print(data)
# {'key': [1, 2, {'nested': True}]}
# pprint: Python-formatted, readable
pprint(data)
# {'key': [1, 2, {'nested': True}]}
# json.dumps: JSON-formatted
print(json.dumps(data, indent=2))
# {
# "key": [
# 1,
# 2,
# {"nested": true}
# ]
# }Use pprint for Python debugging, json.dumps for JSON output.
Quick Reference
from pprint import pprint, pformat, PrettyPrinter
# Print formatted
pprint(obj)
pprint(obj, width=80, depth=None, compact=False)
# Get formatted string
s = pformat(obj)
# Reusable printer
pp = PrettyPrinter(indent=1, width=80, depth=None, compact=False)
pp.pprint(obj)
pp.pformat(obj)| Parameter | Default | Purpose |
|---|---|---|
width | 80 | Line width before wrapping |
depth | None | Max nesting depth |
indent | 1 | Indentation per level |
compact | False | Pack items densely |
sort_dicts | True | Sort dict keys |
stream | stdout | Output destination |
pprint is simple but essential. Use it whenever you need to see what's actually in your data.
React to this post: