Search code examples
pythonpython-3.xformattingpretty-print

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.


Solution

  • 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.

    You may want to look at rich, a third-party library that has some great pretty-printing capabilities, and supports hooks (__rich_repr__); see the documentation on customising pretty-printing.