The pprint module in the standard library provide  a way for printing  data structures in an easy-to-read, formatted style. 

The pprint() is the basic function for pretty printing , this function will take an object and print the contents in a more organized than the regular print() function. The function makes it easy to clearly visualize the hierarchical structure of the data.The effect is especially visible if we are dealing with larger data structures, otherwise, the output  may appear just like with regular print()

regular

data = {'Name':'John Doe',
       'Age':30,
       'Occupation': ['Software Engineer', 'Data Analyst'],
       'Hobbies':['Painting', 'Traveling', 'Cooking'], 
       'Education':{ 'Graduate':['Bachelor of Science','Masters of Science'], 
       'Undergraduate':['Bachelor of Arts','Masters of Arts'] } } 

print(data) 

Compare the example below where the above data is pretty printed

from pprint import pprint

data = {'Name':'John Doe',
       'Age':30,
       'Occupation': ['Software Engineer', 'Data Analyst'],
       'Hobbies':['Painting', 'Traveling', 'Cooking'], 
       'Education':{ 'Graduate':['Bachelor of Science','Masters of Science'], 
       'Undergraduate':['Bachelor of Arts','Masters of Arts'] } } 

pprint(data) 

{'Age': 30,
 'Education': {'Graduate': ['Bachelor of Science', 'Masters of Science'],
               'Undergraduate': ['Bachelor of Arts', 'Masters of Arts']},
 'Hobbies': ['Painting', 'Traveling', 'Cooking'],
 'Name': 'John Doe',
 'Occupation': ['Software Engineer', 'Data Analyst']} 

Limiting nested Outputs

When the nesting in a data structure goes to deep, it may not be desirable to include all the details in the output. We can control the included nesting details by setting the depth parameter. The function will  only print as deep as the specified depth, adding a delimiter(...) to indicate that there is more data beyond the level. 

from pprint import pprint

data = {'Name':'John Doe',
       'Age':30,
       'Occupation': ['Software Engineer', 'Data Analyst'],
       'Hobbies':['Painting', 'Traveling', 'Cooking'], 
       'Education':{ 'Graduate':['Bachelor of Science','Masters of Science'], 
       'Undergraduate':['Bachelor of Arts','Masters of Arts'] } } 

pprint(data, depth = 1) 

Customizing output width

The pprint() function by default uses a width of  80 characters, we can control this by setting the width parameter to the desired number of characters.

from pprint import pprint

data = {'Name':'John Doe',
       'Age':30,
       'Occupation': ['Software Engineer', 'Data Analyst'],
       'Hobbies':['Painting', 'Traveling', 'Cooking'], 
       'Education':{ 'Graduate':['Bachelor of Science','Masters of Science'], 
       'Undergraduate':['Bachelor of Arts','Masters of Arts'] } } 

pprint(data, width = 100) 

Formatting 

The pformat() function is used to format the data without printing it. It returns a string with a formatted representation of the data structure. It is useful for generating organized textual representations of data structures especially for logging purposes.

from pprint import pformat

data = {'Name':'John Doe',
       'Age':30,
       'Occupation': ['Software Engineer', 'Data Analyst'],
       'Hobbies':['Painting', 'Traveling', 'Cooking'], 
       'Education':{ 'Graduate':['Bachelor of Science','Masters of Science'], 
       'Undergraduate':['Bachelor of Arts','Masters of Arts'] } } 

formatted = pformat(data)
print(formatted)

pretty printing custom objects

In custom classes, pretty printing can be enabled by setting the __repr__() method  which will be used to generate and return a string containing a printable representation of an instance.

  

from pprint import pprint 

class Car: 
    def __init__(self, make, model, year): 
         self.make = make 
         self.model = model 
         self.year = year 

    def __repr__(self): 
         return f'{self.make} {self.model} {self.year}' 

cars = [ Car('Ford', 'Mustang', 2004), Car('Ford', 'Fiesta', 2008), Car('Honda', 'Accord', 2012), Car('Toyota', 'Camry', 2018), ]

pprint(cars)