I think py having manager subcommands is a mistake. If you can do pymanager install, what does having py install do the same thing achieve other than add confusion? py.exe doesn’t currently have these subcommands, so there’s no backwards compatibility need. Looking ahead, there’s no hope for cross-platform unification either. Brevity is hardly a concern. So why have more than one way of writing the same thing?
To be clear, I’m not arguing against py.exe being replaced by a PyManager version. Just against it having an explicit install subcommand. I’d much rather tell people to use pymanager install to install Python, than tell them to run py install and then having to add a spiel about the other things also called py, historically and on other platforms.
I’m sympathetic to this argument, but not in the direction you’re hoping. My ideal situation would be to not add any new (top-level) commands at all - supporting pymanager install is a compatibility situation, not the ideal. I’d rather move immediately to “py is the tool for dealing with multiple Python versions” than having to explain two tools (as well as four python[3][w].exe commands), but that isn’t a transition plan.
If accepted, the old-style py installed with 3.14 (and probably 3.13 and 3.12 updates) will print a warning message for py install (and others), so you don’t necessarily have to include the history in your spiel if you don’t want to.
If I launch pymanager from cmd I get this output, giving usage examples with py-manager which doesn’t appear to exist.
Output of `pymanager` command under 'cmd'
Python installation manager 0.1a18
Copyright (c) Python Software Foundation. All Rights Reserved.
Usage:
py-manager <regular Python options>
Launch the default runtime with specified options.
This is the equivalent of the python command.
py-manager -V:<TAG> Launch runtime identified by <TAG>, which should include the
company name if not PythonCore. Regular Python options may
follow this option.
py-manager -<VERSION> Equivalent to -V:PythonCore\<VERSION>. The version must
begin with the digit 3, platform overrides are permitted,
and regular Python options may follow.
py -3 is the equivalent of the python3 command.
py-manager <COMMAND> Run a specific command (see list below).
Find additional information at https://docs.python.org/using/windows.html.
Commands:
py help Show help for Python installation manager commands
py install Download new Python runtimes
py list Shows all installed Python runtimes
py uninstall Remove runtimes from your machine
Global options:
-v, --verbose Increased output (log_level=20)
-vv Further increased output (log_level=10)
-q, --quiet Less output (log_level=30)
-qq Even less output (log_level=40)
-y, --yes Always confirm prompts (confirm=false)
--config=<PATH> Override configuration with JSON file
However if I use Powershell I get the expected outputs with PyManager[1] and with the <regular Python options> example removed under “Usage”, but still get the commands listed with py under “Commands” whether the old py is installed or not.
pymanager -3.13 gets [ERROR] Unexpected argument: -3.13 and pymanager -V:3.13 gets The command pymanager was not recognized.
Git bash gets this too, but without the upper case letters. ↩︎
Yeah, turns out detecting what command was used to launch is actually pretty complicated in this context. I knew it wasn’t trivial, which is why I defaulted to recommending py all the time (in line with the PEP), and I might just have to go back to it.
But since the behaviour actually depends on the command name used as well, it’s probably just going to be safest to make full copies of the executables and embed the setting at compile time. Most of the implementation is in an importable Python module anyway, so it’s not a huge burden.
Yeah, I didn’t update these. It’s still just a static string.
I don’t see that as an ideal to strive for. Having two tools with clearly defined areas of concern is less of a price to pay than having similar looking things with dissimilar semantics: py install, py install.py, py instal, py Instаll. Besides user confusion, you should also have an eye to security with this sort of thing. Okay, so maybe being tricked into installing the latest Python instead of running a Python script is not very high on the list of security hazards, but still, it’s confused deputy territory.
Ah, my thinking was that the ones listed under ‘commands’ were the ones that it would make sense to switch, as none of those work under the old py launcher. The -V/-<version>/<regular Python options> options under usage on the other hand should all just ‘work’ under the old launcher and I don’t think they need to be changed even if the old launcher is present.
If you look at some of the replies to that post later, it’s not quite true because a lot of distributions actually make rustup (which seems like a very similar concept to PyManager) available:
Rust and Python are different in that regard, because the Rust distribution is only needed for development of Rust code. The Python distribution, though, is needed for runtime execution of Python code and Linux distributions certainly want to keep control of that if at all possible, especially as many system utilities nowadays are written in Python.
Well, no, because the idea is that users won’t have the old py launcher, and so all the commands will work. That may not be true for the transition period, but every time someone sets up a clean machine, they’ll only have the py with the commands, and eventually that’ll be everyone.
And if they update the old launcher and start getting warnings for those commands telling them to uninstall it, some percentage are going to uninstall it and they’ll also have all the commands in one place. Sooner than “nobody has the old one” we’ll reach a point where people have the old one by (hopefully informed) choice, and so have no reason to complain that the help text for a different program is telling them about features they’ve chosen not to get.
In any case, I’ve updated it (not released yet) to show the name of the command that was invoked in both places.
Yes that’s the goal, but while things are switching over the commands that you originally did change are those that would work with both versions of py, while the ones you didn’t are the ones that won’t work with the old py.
I think the cross-platform/Linux discussion doesn’t really belong in this thread but I have noted that some distributions appear to be providing uv now, which has its own Python install managing behaviour and I don’t believe they’re disabling that[1] so I don’t think it’s completely out of the question[2].
Although they may be modifying the defaults to stop it installing runtimes automatically ↩︎
As long as it doesn’t interfere with the Python relied on by system utilities ↩︎
As an amusing sidenote, Ubuntu 24.04 does provide a package that installs an unrelated py command:
$ py
La commande « py » n'a pas été trouvée, mais peut être installée avec :
sudo apt install pythonpy
$ apt show pythonpy
Package: pythonpy
Version: 0.4.11b-3.1
Priority: optional
Section: universe/utils
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Tiago Ilieve <tiago.myhro@gmail.com>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 49,2 kB
Depends: python3:any
Suggests: bash-completion
Homepage: https://github.com/Russell91/pythonpy
Download-Size: 10,2 kB
APT-Sources: http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages
Description: 'python -c', with tab completion and shorthand
pythonpy is an utility that facilitates the usage of Python one-liners. The
command 'py' evaluates a string consisting of any Python expression. It can do
anything from simple arithmetic to complex operations, importing modules
automatically. It also comes with tab completion.
.
Its usage is not restricted to single expressions only. There's also the
possibility to pipe data from stdin and to stdout, even generating strings to
be evaluated by other programs.
And then:
$ sudo apt install pythonpy
[...]
$ py --help
/usr/bin/py:29: SyntaxWarning: invalid escape sequence '\.'
if re.match('np(\..*)?$', raw_module_name):
/usr/bin/py:31: SyntaxWarning: invalid escape sequence '\.'
elif re.match('pd(\..*)?$', raw_module_name):
usage: py [-x] [-l] [-c PRE_CMD] [-C POST_CMD] [-V] [-h] [expression]
positional arguments:
expression e.g. py '2 ** 32'
Options:
-x treat each row of stdin as x
-l treat list of stdin as l
-c PRE_CMD run code before expression
-C POST_CMD run code after expression
-V, --version version info
-h, --help show this help message and exit
$ py '2 ** 32'
/usr/bin/py:29: SyntaxWarning: invalid escape sequence '\.'
if re.match('np(\..*)?$', raw_module_name):
/usr/bin/py:31: SyntaxWarning: invalid escape sequence '\.'
elif re.match('pd(\..*)?$', raw_module_name):
4294967296
If there’s an actual suggestion that we should reject this PEP on Windows because an old project on Linux uses the same command name, then by all means, keep discussing it.
If not, it’s off topic. Please start a new thread.
(For completeness, “do the same thing on all platforms” is under Rejected Ideas in the PEP as a deferred idea - we’re not doing it now, but we’re not ruling it out in the future.)
I’ve put up the PRs I intend to merge assuming the acceptance happens (since I’m planning/hoping to be off the computer for the weekend, so giving people who aren’t or who are in a different time zone a chance to review):
changes to cpython repo (primarily deprecation and docs, also support for python PC/layout --preset-pymanager which is used by the release build)
changes to release-tools repo (adding support to the release build/publish, and also doing a well overdue cleanup of the pipelines)
changes to pythondotorg repo (trying my best to update our website, but I would love any help here! This one probably gets split before merging, I expect, and gets dealt with last)
full pymanager repo which I’m intending to have imported under github.com/python, with all core devs having permission to merge (just like cpython) and all triagers having permission to triage (and with a bit of luck, the same CLA as cpython). There’s a few more changes required to make it right (new URLs in places, for example), but otherwise it’s ready for migration
As no reason has been given and here we are, the Steering Council officially accepts PEP 773! Congratulations and thanks @steve.dower and everyone else who has contributed to a great discussion.