Allow `python -m json` to work (in addition to `python -m json.tool`)

After writing a blog post about Python’s many CLI tools recently, I wondered why the json module cannot be run as a script (python -m json.tool works but python -m json does not).

I did some digging and found that this decision was made because at the time the json package was added, there was no way to run a package as a script (only modules could be run as scripts until Python 2.7).

I propose either:

  1. Allowing python -m json and python -m json.tool to both work and update the documentation to note the use of python -m json only
  2. Allowing both to work, but triggering a DeprecationWarning when python -m json.tool is used

I made a branch to see what these changes might look like. That branch includes the DeprecationWarning approach in particular.

I can see a downside to the deprecation approach, if users may be piping both stderr and stdout to a process/file or if users might accidentally copy-paste the deprecation warning text. I can’t think of any downside to making both approaches work (outside of the usual “now there are 2 ways to do it”).

11 Likes

Sounds like a good idea.

I agree about making sure python -m json.tool still does the same thing as python -m json to allow a smooth transition.

I have a slight preference for option 2 (deprecation warning) over option 1 (deprecation in docs). In any case, there’s no rush to remove the old one.

Well, stderr is the place for warnings and errors.

Two ways to do it, but only one obvious way to do it: python -m json

9 Likes

As @trey notes, deprecation warnings in CLI tools, especially ones where you’re likely to be capturing the output for consumption elsewhere get painful fast. Keeping error output on stderr definitely helps, but not as much as simply not emitting the warning in the first place (e.g. I had to give up on emitting the locale coercion warnings because too many CI processes treated “text was emitted on stderr” as a failure condition).

Given we’d be keeping json.tool around anyway to hold the CLI implementation, there’s no real downside to keeping the if __name__ == "__main__" clause at the end and just having a “version changed” notice in the docs that says “CLI invocation changed to python -m json. Compatibility support for python -m json.tool will be retained indefinitely.”

9 Likes

Thanks @hugovk and @ncoghlan for your feedback.

I have now opened an issue for this idea.

5 Likes

This is now done in python/cpython#122884 (by keeping json.tool) and will be in Python 3.14, thank you @trey!

8 Likes