How to use pprint to print an object using the built-in __str__(self) method?

hernamesbarbara picture hernamesbarbara · Feb 3, 2012 · Viewed 28.9k times · Source

I have a Python script which processes a .txt file which contains report usage information. I'd like to find a way to cleanly print the attributes of an object using pprint's pprint(vars(object)) function.

The script reads the file and creates instances of a Report class. Here's the class.

class Report(object):
    def __init__(self, line, headers):
        self.date_added=get_column_by_header(line,headers,"Date Added")
        self.user=get_column_by_header(line,headers,"Login ID")
        self.report=get_column_by_header(line,headers,"Search/Report Description")
        self.price=get_column_by_header(line,headers,"Price")
        self.retail_price=get_column_by_header(line,headers,"Retail Price")

    def __str__(self):
        from pprint import pprint
        return str(pprint(vars(self)))

I'd like to be able to print instances of Report cleanly a-la-pprint.

for i,line in enumerate(open(path+file_1,'r')):
    line=line.strip().split("|")
    if i==0:
        headers=line

    if i==1:
        record=Report(line,headers)
        print record

When I call

print record

for a single instance of Report, this is what I get in the shell.

{'date_added': '1/3/2012 14:06',
'price': '0',
'report': 'some_report',
'retail_price': '0.25',
'user': 'some_username'}
 None

My question is two-fold.

First, is this a good / desired way to print an object's attributes cleanly? Is there a better way to do this with or without pprint?

Second, why does

None

print to the shell at the end? I'm confused where that's coming from.

Thanks for any tips.

Answer

Charles Merriam picture Charles Merriam · May 25, 2014

Dan's solution is just wrong, and Ismail's in incomplete.

  1. __str__() is not called, __repr__() is called.
  2. __repr__() should return a string, as pformat does.
  3. print normally indents only 1 character and tries to save lines. If you are trying to figure out structure, set the width low and indent high.

Here is an example

class S:
    def __repr__(self):
        from pprint import pformat
        return pformat(vars(self), indent=4, width=1)

a = S()
a.b = 'bee'
a.c = {'cats': ['blacky', 'tiger'], 'dogs': ['rex', 'king'] }
a.d = S()
a.d.more_c = a.c

print(a)

This prints

{   'b': 'bee',
    'c': {   'cats': [   'blacky',
                         'tiger'],
             'dogs': [   'rex',
                         'king']},
    'd': {   'more_c': {   'cats': [   'blacky',
                               'tiger'],
                  'dogs': [   'rex',
                              'king']}}}

Which is not perfect, but passable.