Feature or enhancement
Proposal:
Python 3.15 introduces the expand keyword for pprint, which improves the output:
- expand (bool) – If
True, opening parentheses and brackets will be followed by
a newline and the following content will be indented by one level, similar to
pretty-printed JSON. Incompatible with compact.
For example, this code:
from pprint import pprint
config = {
"database": {
"host": "db.example.com",
"port": 5432,
"options": {
"connect_timeout": 5,
"pool_size": 10,
"ssl": True,
"sslmode": "verify-full",
},
},
"logging": {
"level": "INFO",
"file": "/var/log/app.log",
"handlers": {
"console": {"enabled": True},
"file": {"rotate": True, "max_bytes": 1048576},
},
},
}
print("===== expand=False =====")
print()
pprint(config)
print()
print("===== expand=True =====")
print()
pprint(config, expand=True)
Produces:
===== expand=False =====
{'database': {'host': 'db.example.com',
'options': {'connect_timeout': 5,
'pool_size': 10,
'ssl': True,
'sslmode': 'verify-full'},
'port': 5432},
'logging': {'file': '/var/log/app.log',
'handlers': {'console': {'enabled': True},
'file': {'max_bytes': 1048576, 'rotate': True}},
'level': 'INFO'}}
===== expand=True =====
{
'database': {
'host': 'db.example.com',
'options': {
'connect_timeout': 5,
'pool_size': 10,
'ssl': True,
'sslmode': 'verify-full',
},
'port': 5432,
},
'logging': {
'file': '/var/log/app.log',
'handlers': {
'console': {'enabled': True},
'file': {'max_bytes': 1048576, 'rotate': True},
},
'level': 'INFO',
},
}
"Prettiness" is subjective, but in my opinion, the expanded output looks nicer and is much easier to read. It's also closer to code formatted with modern tools like Black and Ruff.
Opinions about pprint
Others also don't like the current default:
For a long time I was unhappy with default values that standard pprint module has
(from pprint import pprint). So, I decided to change them as I like and not pass
them every call to pprint.
https://alex-ber.medium.com/my-pprint-module-f25a7b695e5f
However, it has a very greedy layout algorithm that fails to produce pretty output in
many cases.
https://tommikaikkonen.github.io/introducing-prettyprinter-for-python/
pprint++: a drop-in replacement for pprint that's actually pretty ... Why is it
prettier? Unlike pprint, `pprint++ strives to emit a readable, largely
PEP8-compliant, representation of its input.
https://github.com/wolever/pprintpp
the current output for a large nested dictionary with pprint is basically unusable and
definitely not pretty, which is a shame because large dictionaries are probably the
primary use case for pprint.
#112632 (comment)
When working with deeply nested dictionaries (depth 4+), readability becomes critical.
Python’s built-in `pprint module is the default choice for "pretty printing," but it
often falls short with deep nesting—producing cluttered, inconsistently indented
output that’s hard to parse.
https://www.pythontutorials.net/blog/how-to-pretty-print-nested-dictionaries/
I don't really fancy the way Python's pprint formats the output. [...] But I'd like it
to be [...] in the style of Black
https://stackoverflow.com/questions/69945869/pretty-printing-python-dictionary-lists-in-black-style
Other tools and workarounds
The formatting can be improved by using third-party libraries, for example, rich.print(), and pprintpp and alexber.utils.pprint mentioned above. Or by changing the defaults yourself, or following an oft-recommended and somewhat roundabout print(json.dumps(d, indent=4)).
But pprint is often used for debugging because it's always within arm's reach: you just want to import pprint as pprint and pprint(my_var).
Therefore, I believe it would be beneficial to modernise pprint's defaults:
| argument |
before |
after |
expand |
False |
True |
indent |
1 |
4 |
width |
80 |
88 |
pp()
pp() was added to 3.8 in 2017. It's the same as pprint() but with sort_dicts=False.
This is from the discussion preceding its addition, which considered changing the pprint() default:
I guess the underlying issue here is partly the question of what the pprint module
is for. In my understanding, it's primarily a tool for debugging/introspecting
Python programs, and the reason it talks about "valid input to the interpreter"
isn't because we want anyone to actually feed the data back into the interpreter,
but to emphasize that it provides an accurate what-you-see-is-what's-really-there
view into how the interpreter understands a given object. It also emphasizes that
this is not intended for display to end users; making the output format be "Python
code" suggests that the main intended audience is people who know how to read, well,
Python code, and therefore can be expected to care about Python's semantics.
pprint.pprint() is indeed mostly for debugging, but not always. As an example of what
will break if you change the sorting guarantee: in Mailman 3 the REST etag is
calculated from the pprint.pformat() of the result dictionary before it’s JSON-ified.
If the order is changed, then it’s possible a client will have an incorrect etag for a
structure that is effectively the same.
https://mail.python.org/archives/list/python-dev@python.org/message/UYMINUYHZ3O7B2DKXI7B2T42TYCJFZ3N/
https://mail.python.org/pipermail/python-dev/2017-December/151403.html
I agree changing sort_dicts changes the code output.
But display output is different and is safer to change: parsing the output will get you the same thing. As long as you're not doing brittle character-level parsing, it's essentially the same Python code.
Alternatives
I'm also open to:
- Only change defaults for
pp (similar to this suggestion)
- Add a new function with these defaults, somewhat similar to
pp
- Perhaps a new keyword to define a new style, that would override these defaults
Has this already been discussed elsewhere?
No response given
Links to previous discussion of this feature:
No response
Linked PRs
Feature or enhancement
Proposal:
Python 3.15 introduces the
expandkeyword forpprint, which improves the output:For example, this code:
Produces:
"Prettiness" is subjective, but in my opinion, the expanded output looks nicer and is much easier to read. It's also closer to code formatted with modern tools like Black and Ruff.
Opinions about
pprintOthers also don't like the current default:
https://alex-ber.medium.com/my-pprint-module-f25a7b695e5f
https://tommikaikkonen.github.io/introducing-prettyprinter-for-python/
https://github.com/wolever/pprintpp
#112632 (comment)
https://www.pythontutorials.net/blog/how-to-pretty-print-nested-dictionaries/
https://stackoverflow.com/questions/69945869/pretty-printing-python-dictionary-lists-in-black-style
Other tools and workarounds
The formatting can be improved by using third-party libraries, for example,
rich.print(), andpprintppandalexber.utils.pprintmentioned above. Or by changing the defaults yourself, or following an oft-recommended and somewhat roundaboutprint(json.dumps(d, indent=4)).But
pprintis often used for debugging because it's always within arm's reach: you just want toimport pprint as pprintandpprint(my_var).Therefore, I believe it would be beneficial to modernise
pprint's defaults:expandFalseTrueindent14width8088pp()pp()was added to 3.8 in 2017. It's the same aspprint()but withsort_dicts=False.This is from the discussion preceding its addition, which considered changing the
pprint()default:https://mail.python.org/archives/list/python-dev@python.org/message/UYMINUYHZ3O7B2DKXI7B2T42TYCJFZ3N/
https://mail.python.org/pipermail/python-dev/2017-December/151403.html
I agree changing
sort_dictschanges the code output.But display output is different and is safer to change: parsing the output will get you the same thing. As long as you're not doing brittle character-level parsing, it's essentially the same Python code.
Alternatives
I'm also open to:
pp(similar to this suggestion)ppHas this already been discussed elsewhere?
No response given
Links to previous discussion of this feature:
No response
Linked PRs
pprint#149190