Of course! Let's break down pprint in Python, comparing it to the standard print() function and showing you how to use it effectively.

The Short Answer: pprint vs. print
The main difference is that print() is for humans to read quickly, while pprint (Pretty-Print) is for humans to read complex data structures easily.
print(): Outputs data as a single, unformatted string. It's fast and simple.pprint(): Outputs data in a clean, organized, and readable format, especially for nested structures like dictionaries and lists. It's slower but much more useful for debugging and inspecting data.
When to Use pprint?
You should strongly consider using pprint when you are working with:
- Deeply Nested Data: Dictionaries inside lists, lists inside dictionaries, etc.
- Large Dictionaries: When you need to see all the keys and values without them running off the screen.
- Debugging: When you're trying to understand the structure of a complex object you received from an API or a database.
- Configuration Files: Pretty-printing is great for generating or viewing well-formatted JSON or YAML.
The Problem with print()
Let's see why print() can be unhelpful with complex data.
Imagine you have this dictionary:

data = {
'name': 'John Doe',
'age': 30,
'courses': [
{'title': 'History', 'credits': 3},
{'title': 'Math', 'credits': 4},
{'title': 'Science', 'credits': 3}
],
'address': {
'street': '123 Main St',
'city': 'Anytown',
'zip_code': '12345'
}
}
# Using the standard print() function
print(data)
Output:
{'name': 'John Doe', 'age': 30, 'courses': [{'title': 'History', 'credits': 3}, {'title': 'Math', 'credits': 4}, {'title': 'Science', 'credits': 3}], 'address': {'street': '123 Main St', 'city': 'Anytown', 'zip_code': '12345'}}
This is a single, long line of text. It's very difficult to parse the structure at a glance. Where does the courses list end? Where does the address dictionary start?
The Solution with pprint
Now, let's use the pprint module. First, you need to import it.
import pprint
data = {
'name': 'John Doe',
'age': 30,
'courses': [
{'title': 'History', 'credits': 3},
{'title': 'Math', 'credits': 4},
{'title': 'Science', 'credits': 3}
],
'address': {
'street': '123 Main St',
'city': 'Anytown',
'zip_code': '12345'
}
}
# Using pprint.pprint()
pprint.pprint(data)
Output:

{'address': {'city': 'Anytown',
'street': '123 Main St',
'zip_code': '12345'},
'age': 30,
'courses': [{'credits': 3, 'title': 'History'},
{'credits': 4, 'title': 'Math'},
{'credits': 3, 'title': 'Science'}],
'name': 'John Doe'}
Wow, what a difference!
- Line Breaks and Indentation:
pprintautomatically breaks the data into multiple lines and uses indentation to show the hierarchy. You can clearly see theaddressdictionary and thecourseslist. - Sorted Keys: By default,
pprintsorts the keys of dictionaries alphabetically. This makes it much easier to find a specific key. - Readable Formatting: The output is clean and structured, mimicking how you might write the data by hand.
Key Features and Customization of pprint
pprint is more than just a pretty printer; it's configurable.
a. pprint.pprint() vs. pprint.pformat()
pprint.pprint(object): Prints the object directly to the standard output (your console). It's for immediate viewing.pprint.pformat(object): Returns a string of the pretty-formatted object. This is useful if you want to save the formatted output to a file or a variable.
import pprint
data = {'key': 'value', 'another_key': [1, 2, 3]}
# Get a formatted string
formatted_string = pprint.pformat(data)
print("This is a formatted string:")
print(formatted_string)
# You can now use this string elsewhere, for example, in a file
with open('data.txt', 'w') as f:
f.write(formatted_string)
b. Controlling Width
The width argument lets you specify the maximum number of characters per line.
import pprint
data = {'this_is_a_very_long_key_name': 'this_is_a_very_long_value_string'}
# Default width (usually 80)
print("Default width:")
pprint.pprint(data)
# Custom width
print("\nCustom width (40):")
pprint.pprint(data, width=40)
Output:
Default width:
{'this_is_a_very_long_key_name': 'this_is_a_very_long_value_string'}
Custom width (40):
{'this_is_a_very_long_key_name': 'this_is_a_very_long_value_string'}
(Note: In this simple case, the string is too long to be broken, so it doesn't change. But with more complex data, you'd see the difference.)
c. Controlling Indentation
The indent argument controls the number of spaces used for each level of nesting.
import pprint
data = {'level1': {'level2': {'level3': 'value'}}}
print("Default indent (usually 1):")
pprint.pprint(data)
print("\nCustom indent (4):")
pprint.pprint(data, indent=4)
Output:
Default indent (usually 1):
{'level1': {'level2': {'level3': 'value'}}}
Custom indent (4):
{'level1': {'level2': {'level3': 'value'}}}
d. Disabling Sorting
If you want to preserve the original order of dictionary keys (Python 3.7+), you can set sort_dicts=False.
import pprint
# In Python 3.7+, dictionaries preserve insertion order
data = {'zebra': 1, 'apple': 2, 'banana': 3}
print("With sorting (default):")
pprint.pprint(data)
print("\nWithout sorting:")
pprint.pprint(data, sort_dicts=False)
Output:
With sorting (default):
{'apple': 2, 'banana': 3, 'zebra': 1}
Without sorting:
{'zebra': 1, 'apple': 2, 'banana': 3}
A Quick Look at pprint.pprint vs. json.dumps
For dictionaries that can be converted to JSON, json.dumps is another excellent option for pretty-printing.
import json
import pprint
data = {'name': 'John', 'courses': [{'title': 'Math', 'credits': 4}]}
# Using pprint
print("--- pprint ---")
pprint.pprint(data)
# Using json.dumps
print("\n--- json.dumps ---")
# The 'indent' argument works similarly here
print(json.dumps(data, indent=4))
Output:
--- pprint ---
{'courses': [{'credits': 4, 'title': 'Math'}], 'name': 'John'}
--- json.dumps ---
{
"name": "John",
"courses": [
{
"title": "Math",
"credits": 4
}
]
}
Key Difference: json.dumps will only work on objects that are JSON-serializable (e.g., strings, numbers, lists, dictionaries, True/False/None). pprint can handle almost any Python object, including sets, custom class instances, and more complex types.
Summary Table
| Feature | print() |
pprint.pprint() |
|---|---|---|
| Purpose | Quick, simple output for general use. | Pretty-printing complex data structures for readability. |
| Output Format | Single, unformatted line. | Multi-line, indented, sorted (by default). |
| Performance | Very Fast. | Slower due to formatting logic. |
| Best For | Simple variables, status messages, loops. | Debugging, inspecting APIs, nested data. |
| Customization | Limited (e.g., sep, end). |
High: width, indent, sort_dicts, etc. |
| Return Value | None (prints to console). |
Returns a formatted string (pformat). |
Final Recommendation:
- Use
print()for 90% of your printing needs. - Use
pprint.pprint()the moment you find yourself squinting at the console to understand the structure of a variable, especially a dictionary or list. It will save you a lot of time and headaches.
