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.
pprint
is just another form of print. When you say pprint(vars(self))
it prints vars into stdout and returns none because it is a void function. So when you cast it to a string it turns None
(returned by pprint
) into a string which is then printed from the initial print statement. I would suggest changing your print to pprint
or redefine print as print if its all you use it for.
def __str__(self):
from pprint import pprint
return str(vars(self))
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)
pprint record
One alternative is to use a formatted output:
def __str__(self):
return "date added: %s\nPrice: %s\nReport: %s\nretail price: %s\nuser: %s" % tuple([str(i) for i in vars(self).values()])
Hope this helped
Dan's solution is just wrong, and Ismail's in incomplete.
__str__()
is not called,__repr__()
is called.__repr__()
should return a string, as pformat does.- 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.
pprint.pprint
doesn't return a string; it actually does the printing (by default to stdout, but you can specify an output stream). So when you write print record
, record.__str__()
gets called, which calls pprint
, which returns None
. str(None)
is 'None'
, and that gets print
ed, which is why you see None
.
You should use pprint.pformat
instead. (Alternatively, you can pass a StringIO
instance to pprint
.)
For pretty-printing objects which contain other objects, etc. pprint
is not enough. Try IPython's lib.pretty, which is based on a Ruby module.
from IPython.lib.pretty import pprint
pprint(complex_object)
I think beeprint is what you need.
Just pip install beeprint
and change your code to:
def __str__(self):
from beeprint import pp
return pp(self, output=False)
来源:https://stackoverflow.com/questions/9135485/how-to-use-pprint-to-print-an-object-using-the-built-in-str-self-method