The pprint module formats data structures with proper indentation and line breaks. When print() gives you an unreadable mess, pprint makes it human-friendly.

The Problem

Regular print squashes everything:

data = {'users': [{'name': 'Alice', 'scores': [95, 87, 92]}, {'name': 'Bob', 'scores': [78, 85, 90]}], 'metadata': {'version': 1, 'updated': '2024-01-15'}}
 
print(data)
# {'users': [{'name': 'Alice', 'scores': [95, 87, 92]}, {'name': 'Bob', 'scores': [78, 85, 90]}], 'metadata': {'version': 1, 'updated': '2024-01-15'}}

Basic Pretty Print

from pprint import pprint
 
data = {
    'users': [
        {'name': 'Alice', 'scores': [95, 87, 92]},
        {'name': 'Bob', 'scores': [78, 85, 90]}
    ],
    'metadata': {'version': 1, 'updated': '2024-01-15'}
}
 
pprint(data)

Output:

{'metadata': {'updated': '2024-01-15', 'version': 1},
 'users': [{'name': 'Alice', 'scores': [95, 87, 92]},
           {'name': 'Bob', 'scores': [78, 85, 90]}]}

Controlling Width

Adjust line width:

from pprint import pprint
 
data = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
 
# Default width (80)
pprint(data)
# {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
 
# Narrow width forces wrapping
pprint(data, width=20)
# {'a': 1,
#  'b': 2,
#  'c': 3,
#  'd': 4,
#  'e': 5}

Indentation

Control indent level:

from pprint import pprint
 
data = {'outer': {'inner': {'deep': [1, 2, 3]}}}
 
pprint(data, indent=4)
# {   'outer': {   'inner': {   'deep': [1, 2, 3]}}}

Depth Limiting

Hide deeply nested content:

from pprint import pprint
 
data = {'level1': {'level2': {'level3': {'level4': 'deep'}}}}
 
pprint(data, depth=2)
# {'level1': {'level2': {...}}}

Getting the String

Use pformat to get the string instead of printing:

from pprint import pformat
 
data = {'a': [1, 2, 3], 'b': [4, 5, 6]}
formatted = pformat(data)
 
# Use in logging, files, etc.
with open('debug.txt', 'w') as f:
    f.write(formatted)

Sorting Keys

Keys are sorted by default in Python 3.8+. Disable it:

from pprint import pprint
 
data = {'zebra': 1, 'apple': 2, 'mango': 3}
 
# Default: sorted
pprint(data)
# {'apple': 2, 'mango': 3, 'zebra': 1}
 
# Preserve insertion order
pprint(data, sort_dicts=False)
# {'zebra': 1, 'apple': 2, 'mango': 3}

Compact Mode

Fit more on each line:

from pprint import pprint
 
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
# Normal
pprint(data, width=30)
# [1,
#  2,
#  3,
#  ...]
 
# Compact
pprint(data, width=30, compact=True)
# [1, 2, 3, 4, 5, 6, 7,
#  8, 9, 10]

PrettyPrinter Class

For repeated use with the same settings:

from pprint import PrettyPrinter
 
pp = PrettyPrinter(indent=2, width=60, depth=3)
 
pp.pprint({'data': [1, 2, 3]})
pp.pprint({'more': {'nested': 'data'}})

Debugging Example

from pprint import pprint
 
def debug_response(response):
    print("=== API Response ===")
    pprint(response, depth=3, width=100)
    print("====================")
 
# Much more readable than print()
debug_response({
    'status': 200,
    'data': {
        'users': [...],
        'pagination': {'page': 1, 'total': 100}
    }
})

With Logging

import logging
from pprint import pformat
 
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
 
data = {'complex': {'nested': {'structure': [1, 2, 3]}}}
logger.debug("Received data:\n%s", pformat(data))

Custom Objects

pprint works with any object that has a readable __repr__:

from pprint import pprint
 
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email
    
    def __repr__(self):
        return f"User({self.name!r}, {self.email!r})"
 
users = [User('Alice', 'alice@example.com'), User('Bob', 'bob@example.com')]
pprint(users)
# [User('Alice', 'alice@example.com'),
#  User('Bob', 'bob@example.com')]

pprint vs json.dumps

For JSON-like output:

import json
from pprint import pprint
 
data = {'name': 'Alice', 'scores': [95, 87]}
 
# pprint: Python repr style
pprint(data)
# {'name': 'Alice', 'scores': [95, 87]}
 
# json.dumps: JSON style
print(json.dumps(data, indent=2))
# {
#   "name": "Alice",
#   "scores": [95, 87]
# }

Use json.dumps when you need valid JSON. Use pprint for Python debugging.

When to Use pprint

Use pprint when:

  • Debugging complex nested structures
  • Logging data for human review
  • Quick inspection in REPL
  • Writing debug output to files

Don't use when:

  • You need valid JSON output
  • Performance matters (pprint is slower than print)
  • Output will be parsed by another program

For readable debugging output, pprint is the quick solution that's always available in the standard library.

React to this post: