Skip to content

Commit 4c25308

Browse files
warsawhugovkAA-Turnerwillingcericvsmith
authored
PEP 813: The Pretty Print Protocol (#4690)
* PEP 813: The Pretty Print Protocol Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Carol Willing <carolcode@willingconsulting.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Eric V. Smith <eric@trueblade.com>
1 parent 2888c00 commit 4c25308

File tree

2 files changed

+256
-1
lines changed

2 files changed

+256
-1
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ peps/pep-0808.rst @FFY00
687687
peps/pep-0809.rst @zooba
688688
peps/pep-0810.rst @pablogsal @DinoV @Yhg1s
689689
peps/pep-0811.rst @sethmlarson @gpshead
690-
# ...
690+
peps/pep-0813.rst @warsaw @ericvsmith
691691
peps/pep-0814.rst @vstinner @corona10
692692
peps/pep-0815.rst @emmatyping
693693
peps/pep-0816.rst @brettcannon

peps/pep-0813.rst

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
PEP: 813
2+
Title: The Pretty Print Protocol
3+
Author: Barry Warsaw <barry@python.org>, Eric V. Smith <eric@trueblade.com>
4+
Discussions-To: Pending
5+
Status: Draft
6+
Type: Standards Track
7+
Created: 07-Nov-2025
8+
Python-Version: 3.15
9+
Post-History: Pending
10+
11+
12+
Abstract
13+
========
14+
15+
This PEP describes the "pretty print protocol", a collection of changes proposed to make pretty printing more
16+
customizable and convenient.
17+
18+
19+
Motivation
20+
==========
21+
22+
"Pretty printing" is a feature which provides a capability to format object representations for better
23+
readability. The core functionality is implemented by the standard library :mod:`pprint` module. ``pprint``
24+
includes a class and APIs which users can invoke to format and print more readable representations of objects,
25+
versus the standard ``repr()`` built-in function. Important use cases include pretty printing large
26+
dictionaries and other complicated objects for debugging purposes.
27+
28+
This PEP builds on the features of the module to provide more customization and user convenience. It is also
29+
inspired by the `Rich library's pretty printing protocol <rich-repr-protocol_>`_.
30+
31+
32+
Rationale
33+
=========
34+
35+
Pretty printing is very useful for displaying complex data structures, like dictionaries read from JSON
36+
content. However, the existing :mod:`pprint` module can only format builtin objects that it knows about.
37+
By providing a way for classes to customize how their instances participate in pretty printing,
38+
users have more options for visually improving the display of their complex data, especially for debugging.
39+
40+
By extending the built-in :func:`print` function to automatically pretty print its output, debugging with
41+
user-friendly display is made even more convenient. Since no extra imports are required, users can easily
42+
just piggyback on well-worn "print debugging" patterns, at least for the most common use cases.
43+
44+
These extensions work both independently and complimentary, to provide powerful new use cases.
45+
46+
47+
Specification
48+
=============
49+
50+
There are several parts to this proposal.
51+
52+
53+
``__pprint__()`` methods
54+
------------------------
55+
56+
Classes can implement a new dunder method, ``__pprint__()`` which if present, generates parts of their
57+
instance's pretty printed representation. This augments ``__repr__()`` which, prior to this proposal, was the
58+
only method used to generate a custom representation of the object. Since object reprs provide functionality
59+
distinct from pretty printing, some classes may want more control over their pretty display. The
60+
:py:class:`python:pprint.PrettyPrinter` class is modified to respect an object's ``__pprint__()`` method if
61+
present.
62+
63+
``__pprint__()`` is optional; if missing, the standard pretty printers fall back to ``__repr__()`` for full
64+
backward compatibility (technically speaking, :py:func:`python:pprint.saferepr` is used). However, if defined
65+
on a class, ``__pprint__()`` takes a single argument, the object to be pretty printed (i.e. ``self``).
66+
67+
The method is expected to return or yield a sequence of values, which are used to construct a pretty
68+
representation of the object. These values are wrapped in standard class "chrome", such as the
69+
class name. The printed representation will usually look like a class constructor, with positional,
70+
keyword, and default arguments. The values can be any of the following formats:
71+
72+
* A single value, representing a positional argument. The value itself is used.
73+
* A 2-tuple of ``(name, value)`` representing a keyword argument. A representation of
74+
``name=value`` is used.
75+
* A 3-tuple of ``(name, value, default_value)`` representing a keyword argument with a default
76+
value. If ``value`` equals ``default_value``, then this tuple is skipped, otherwise
77+
``name=value`` is used.
78+
79+
.. note::
80+
81+
This protocol is compatible with the `Rich library's pretty printing protocol
82+
<https://rich.readthedocs.io/en/latest/pretty.html#rich-repr-protocol>`_.
83+
84+
85+
A new argument to built-in ``print``
86+
------------------------------------
87+
88+
Built-in :func:`print` takes a new optional argument, appended to the end of the argument list, called
89+
``pretty``, which can take one of the following values:
90+
91+
* ``None`` - the default. No pretty printing is invoked. Fully backward compatible.
92+
* ``True`` - use a temporary instance of the :py:class:`python:pprint.PrettyPrinter` class to get a
93+
pretty representation of the object.
94+
* An instance with a ``pformat()`` method, which has the same signature as
95+
:py:meth:`python:pprint.PrettyPrinter.pformat`. When given, this will usually be an instance of a
96+
subclass of ``PrettyPrinter`` with its ``pformat()`` method overridden. Note that this form
97+
requires **an instance** of a pretty printer, not a class, as only ``print(..., pretty=True)``
98+
performs implicit instantiation.
99+
100+
101+
Additions to ``f-strings`` and ``str.format()``
102+
-----------------------------------------------
103+
104+
In addition to the existing ``!s``, ``!r``, and ``!a`` conversion specifiers, an additional ``!p`` conversion
105+
will be added. The effect of this specifier with an expression ``value`` will be to call
106+
:py:func:`python:pprint.pformat`, passing ``value`` as the only argument. In this initial specification, it
107+
will be an error to provide any format specifier if ``!p`` is used.
108+
109+
Examples
110+
========
111+
112+
A custom ``__pprint__()`` method can be used to customize the representation of the object, such as with this
113+
class:
114+
115+
.. code-block:: python
116+
117+
class Bass:
118+
def __init__(self, strings: int, pickups: str, active: bool=False):
119+
self._strings = strings
120+
self._pickups = pickups
121+
self._active = active
122+
123+
def __pprint__(self):
124+
yield self._strings
125+
yield 'pickups', self._pickups
126+
yield 'active', self._active, False
127+
128+
Now let's create a couple of instances, and pretty print them:
129+
130+
.. code-block:: pycon
131+
132+
>>> precision = Bass(4, 'split coil P', active=False)
133+
>>> stingray = Bass(5, 'humbucker', active=True)
134+
135+
>>> pprint.pprint(precision)
136+
Bass(4, pickups='split coil P')
137+
>>> pprint.pprint(stingray)
138+
Bass(5, pickups='humbucker', active=True)
139+
140+
Here's an example of using the ``pretty`` argument to built-in ``print()``:
141+
142+
.. code-block:: pycon
143+
144+
>>> import os
145+
>>> print(os.pathconf_names)
146+
{'PC_ASYNC_IO': 17, 'PC_CHOWN_RESTRICTED': 7, 'PC_FILESIZEBITS': 18, 'PC_LINK_MAX': 1, 'PC_MAX_CANON': 2, 'PC_MAX_INPUT': 3, 'PC_NAME_MAX': 4, 'PC_NO_TRUNC': 8, 'PC_PATH_MAX': 5, 'PC_PIPE_BUF': 6, 'PC_PRIO_IO': 19, 'PC_SYNC_IO': 25, 'PC_VDISABLE': 9, 'PC_MIN_HOLE_SIZE': 27, 'PC_ALLOC_SIZE_MIN': 16, 'PC_REC_INCR_XFER_SIZE': 20, 'PC_REC_MAX_XFER_SIZE': 21, 'PC_REC_MIN_XFER_SIZE': 22, 'PC_REC_XFER_ALIGN': 23, 'PC_SYMLINK_MAX': 24}
147+
148+
>>> print(os.pathconf_names, pretty=True)
149+
{'PC_ALLOC_SIZE_MIN': 16,
150+
'PC_ASYNC_IO': 17,
151+
'PC_CHOWN_RESTRICTED': 7,
152+
'PC_FILESIZEBITS': 18,
153+
'PC_LINK_MAX': 1,
154+
'PC_MAX_CANON': 2,
155+
'PC_MAX_INPUT': 3,
156+
'PC_MIN_HOLE_SIZE': 27,
157+
'PC_NAME_MAX': 4,
158+
'PC_NO_TRUNC': 8,
159+
'PC_PATH_MAX': 5,
160+
'PC_PIPE_BUF': 6,
161+
'PC_PRIO_IO': 19,
162+
'PC_REC_INCR_XFER_SIZE': 20,
163+
'PC_REC_MAX_XFER_SIZE': 21,
164+
'PC_REC_MIN_XFER_SIZE': 22,
165+
'PC_REC_XFER_ALIGN': 23,
166+
'PC_SYMLINK_MAX': 24,
167+
'PC_SYNC_IO': 25,
168+
'PC_VDISABLE': 9}
169+
170+
171+
Backwards Compatibility
172+
=======================
173+
174+
When none of the new features are used, this PEP is fully backward compatible, both for built-in
175+
``print()`` and the ``pprint`` module.
176+
177+
178+
Security Implications
179+
=====================
180+
181+
There are no known security implications for this proposal.
182+
183+
184+
How to Teach This
185+
=================
186+
187+
Documentation and examples are added to the ``pprint`` module and the ``print()`` function.
188+
Beginners don't need to be taught these new features until they want prettier representations of
189+
their objects.
190+
191+
192+
Reference Implementation
193+
========================
194+
195+
The reference implementation is currently available as a `PEP author branch of the CPython main
196+
branch <https://github.com/warsaw/cpython/tree/pprint>`__.
197+
198+
199+
Rejected Ideas
200+
==============
201+
202+
None at this time.
203+
204+
205+
Open Issues
206+
===========
207+
208+
The output format and APIs are heavily inspired by `Rich
209+
<rich-repr-protocol_>`_. The idea is that Rich could
210+
implement an API compatible with ``print(..., pretty=RichPrinter)`` fairly easily. Rich's API is designed to
211+
print constructor-like representations of instances, which means that it's not possible to control much of the
212+
"class chrome" around the arguments. Rich does support using angle brackets (i.e. ``<...>``) instead of
213+
parentheses by setting the attribute ``.angular=True`` on the rich repr method. This PEP does not support
214+
that feature, although it likely could in the future.
215+
216+
This also means that there's no way to control the pretty printed format of built-in types like strings,
217+
dicts, lists, etc. This seems fine as ``pprint`` is not intended to be as feature-rich (pun intended!) as
218+
Rich. This PEP purposefully deems such fancy features as out-of-scope.
219+
220+
One consequence of ``print(..., pretty=True)`` is that it can be more less obvious if you wanted to print
221+
multiple objects with, say a newline between the object representations. Compare these two outputs:
222+
223+
.. code-block:: pycon
224+
225+
>>> print(precision, '\n', stingray, pretty=True)
226+
Bass(4, pickups='split coil P') '\n' Bass(5, pickups='humbucker', active=True)
227+
228+
>>> print(precision, stingray, sep='\n', pretty=True)
229+
Bass(4, pickups='split coil P')
230+
Bass(5, pickups='humbucker', active=True)
231+
232+
It's likely you'll want the second output, but more complicated multi-object displays could get even less
233+
convenient and/or more verbose.
234+
235+
236+
Acknowledgments
237+
===============
238+
239+
TBD
240+
241+
242+
Footnotes
243+
=========
244+
245+
TBD
246+
247+
248+
Copyright
249+
=========
250+
251+
This document is placed in the public domain or under the
252+
CC0-1.0-Universal license, whichever is more permissive.
253+
254+
255+
.. _rich-repr-protocol: https://rich.readthedocs.io/en/stable/pretty.html#rich-repr-protocol

0 commit comments

Comments
 (0)