Update: upon the encouragement of a few CPython core team members, I opened a pull request to add this to Python 3.14.
Have you ever used Python’s json.tool
command-line interface?
You can run python -m json.tool
against a JSON file and Python will print a nicely formatted version of the file.
1 2 3 4 5 6 7 |
|
Why do we need to run json.tool
instead of json
?
The history of python -m
Python 3.5 added the ability to run a module as a command-line script using the -m
argument (see PEP 338) which was implemented in Python 2.5.
While that feature was being an additional feature/bug was accidentally added, alowing packages to be run with the -m
flag as well.
When a package was run with the -m
flag, the package’s __init__.py
file would be run, with the __name__
variable set to __main__
.
This accidental feature/bug was removed in Python 2.6.
It wasn’t until Python 2.7 that the ability to run python -m package
was re-added (see below).
The history of the json
module
The json
module was added in Python 2.6.
It was based on the third-party simplejson
library.
That library originally relied on the fact that Python packages could be run with the -m
flag to run the package’s __init__.py
file with __name__
set to __main__
(see this code from version 1.8.1).
When simplejson
was added to Python as the json
module in Python 2.6, this bug/feature could no longer be relied upon as it was fixed in Python 2.6.
To continue allowing for a nice command-line interface, it was decided that running a tool
submodule would be the way to add a command-line interface to the json
package (discussion here).
Python 2.7 added the ability to run any package as a command-line tool.
The package would simply need a __main__.py
file within it, which Python would run as the entry point to the package.
At this point, json.tool
had already been added in Python 2.6 and no attempt was made (as far as I can tell) to allow python -m json
to work instead.
Once you’ve added a feature, removing or changing it can be painful.
Could we make python -m json
work today?
We could.
We would just need to rename tool.py
to __main__.py
.
To allow json.tool
to still work also, would could make a new tool.py
module that simply imports json.__main__
.
We could even go so far as to deprecate json.tool
if we wanted to.
Should we do this though? 🤔
Should we make python -m json
work?
I don’t know about you, but I would rather type python -m json
than python -m json.tool
.
It’s more memorable and easier to guess, if you’re not someone who has memorized all the command-line tools hiding in Python.
But would this actually be used? I mean, don’t people just use the jq tool instead?
Well, a sqlite3
shell was added to Python 3.12 despite the fact that third-party interactive sqlite prompts are fairly common.
It is pretty handy to have a access to a tool within an unfamiliar environment where installing yet-another-tool might pose a problem. Think Docker, a locked-down Windows machine, or any computer without network or with network restrictions.
Personally, I’d like to see python3 -m json
work.
I can’t think of any big downsides.
Can you?
Update: pull request opened.
Too long; didn’t read
The “too long didn’t read version”:
- Python 2.5 added support for the
-m
argument for modules, but not packages - A third-party
simplejson
app existed with a nice CLI that relied on a-m
implementation bug allowing packages to be run using-m
- Python 2.6 fixed that implementation quirk and broke the previous ability to run
python -m simplejson
- Python 2.6 also added the
json
module, which was based on this third-partysimplejson
package - Since
python -m json
couldn’t work anymore, the ability to runpython -m json.tool
was added - Python 2.7 added official support for
python -m some_package
by running a__main__
submodule - The
json.tool
module already existed in Python 2.6 and the ability to runpython -m json
was (as far as I can tell) never seriously considered
All thanks to git history and issue trackers
I discovered this by noting the first commit that added the tool
submodule to simplejson
, which notes the fact that this was for consistency with the new json
standard library module.
Thank you git history.
And thank you to the folks who brought us the simplejson
library, the json
module, and the ability to use -m
on both a module and a package!
Also, thank you to Alyssa Coghlan, Hugo van Kemenade, and Adam Turner for reviewing my pull request to add this feature to Python 3.14. 💖