Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Python 3's PrettyPrinter behaving differently from Python 2's, and how do I get the same behavior?

When I try running this code:

from pprint import PrettyPrinter

class MyPrettyPrinter(PrettyPrinter):
    def __init__(self, *args, **kwargs):
        PrettyPrinter.__init__(self, *args, **kwargs)
    def format(self, object, context, maxlevels, level):
        (repr, readable, recursive) = PrettyPrinter.format(self, object, context, maxlevels, level)
        return (type(repr)(object), readable, recursive) if isinstance(object, str) else (repr, readable, recursive)

print(MyPrettyPrinter().pformat(['x']))

I get a different output in Python 3 (['x']) than I get in Python 2 ([x]).

Why is this, and how do I get the same behavior as in Python 2?

like image 440
user541686 Avatar asked Apr 25 '26 10:04

user541686


1 Answers

This is how Python 3’s internal _format function works:

def _format(self, object, stream, indent, allowance, context, level):
    # …
    rep = self._repr(object, context, level - 1)
    max_width = self._width - 1 - indent - allowance
    sepLines = len(rep) > max_width

    if sepLines:
        # … custom repr logic
    write(rep)

As you can see, if the the output of _repr fits into a single line, then no custom logic for generating the repr is used. self._repr delegates to self.format, which essentially just does a more complex repr(). So this is just called once if the output fits in a single line; otherwise, the output is not used but the (here: sequence) element is split into multiple parts, and the logic is again invoked for subelements.

In comparison, Python 2’s _format implements a completely custom logic at any stage, always invoking the custom formatter for all subelements in lists. That’s why your trigger works in Python 2 but does not in Python 3.

Unfortunately, I don’t see any simple way to hook into this without replicating a lot of the logic that’s in the new Python 3 implementation.

like image 53
poke Avatar answered Apr 27 '26 23:04

poke