Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make my class pretty printable in Python?

Python has a pretty printer (pprint(...)). I would like to make my classes pretty printable. Will pretty print print my instances in a better way, if I provide a certain interface?

The Python documentation in section 8.11 shows different examples, but no example how to make a user defined class pretty printable.

So what interface need my classes to provide?
Is there any other (maybe better) formatter?


Use Case:

I want to pretty print the content of ConfigParser, for which I have create an extended version called ExtendenConfigParser. So I have the possibility to add more functionality or add a matching pretty print interface.

like image 568
Paebbels Avatar asked Nov 27 '16 11:11

Paebbels


People also ask

Which module is required in pretty printing?

The pprint module provides a capability to “pretty-print” arbitrary Python data structures in a form which can be used as input to the interpreter.

What does pretty print do?

Prettyprint is the process of converting and presenting source code or other objects in a legible and attractive way. A prettyprinter takes blocks of code and prints them in an aesthetically pleasing fashion, presenting the characters with line breaks and indentations to make the code comprehensible.


2 Answers

pprint does not look for any hooks. The pprint.PrettyPrinter uses a dispatch pattern instead; a series of methods on the class that are keyed on class.__repr__ references.

You can subclass pprint.PrettyPrinter to teach it about your class:

class YourPrettyPrinter(pprint.PrettyPrinter):
    _dispatch = pprint.PrettyPrinter._dispatch.copy()

    def _pprint_yourtype(self, object, stream, indent, allowance, context, level):
        stream.write('YourType(')
        self._format(object.foo, stream, indent, allowance + 1,
                     context, level)
        self._format(object.bar, stream, indent, allowance + 1,
                     context, level)
        stream.write(')')

    _dispatch[YourType.__repr__] = _pprint_yourtype

then use the class directly to pretty print data containing YourType instances. Note that this is contingent on the type having their own custom __repr__ method!

You can also plug functions directly into the PrettyPrinter._dispatch dictionary; self is passed in explicitly. This is probably the better option for a 3rd-party library:

from pprint import PrettyPrinter

if isinstance(getattr(PrettyPrinter, '_dispatch'), dict):
     # assume the dispatch table method still works
     def pprint_ExtendedConfigParser(printer, object, stream, indent, allowance, context, level):
         # pretty print it!
     PrettyPrinter._dispactch[ExtendedConfigParser.__repr__] = pprint_ExtendedConfigParser

See the pprint module source code for how the other dispatch methods are written.

As always, single-underscore names like _dispatch are internal implementation details that can be altered in a future version. However, it is the best option you have here. The dispatch table was added in Python 3.5 and is present in at least Python 3.5 - 3.9 alpha.

like image 96
Martijn Pieters Avatar answered Oct 14 '22 00:10

Martijn Pieters


It is not really a solution, but I usually just make objects serializable and pretty print them like this:

pprint(obj.dict())
like image 33
aiven Avatar answered Oct 13 '22 23:10

aiven