There are two major architectural differences.
The first is what @Rosuav pointed out. py
actually parses shebangs, which would otherwise be meaningless on Windows.
The second is how system-wide installed applications are organized. On Linux, the default expectation is that your executables are side by side, directly in folders like /usr/bin
, and then the corresponding “support” files are in corresponding places like /usr/lib
. But on Windows, the default expectation is that each application, with all its support, gets a separate subfolder within C:\Program Files
.
That causes two major problems. First, it breaks tools that can’t handle spaces in paths - you could argue that those are already broken, but it does end up causing a lot of complaints. But that isn’t really relevant for our purposes.
More importantly, it means that each new application is not automatically put into a place that’s on the PATH - because PATH (on both Linux and Windows) specifies exact folders to check, not folders to search. Putting C:\Program Files
on PATH wouldn’t help (and isn’t normally done); PATH needs a separate entry for each new application.
So, installers are tasked with modifying PATH to add the new application each time, if they so desire. And there’s a not-super-generous total length limit on PATH (as I understand things, this is 4096 bytes used to store UTF-16 text - typically documented as “2048 characters”, but, you know, surrogate pairs…).
Before py
was added for the Windows releases, Python installers did modify PATH by default, and also included the aliases you describe. They would sort of work, in that python3
would find the python3.exe
in the first folder on PATH that contained one (corresponding to the most recently installed 3.x Python); and in particular it would not find a 2.x Python, even if you installed one later, because those installations simply didn’t have that alias. But this still means potentially having multiple useless (shadowed) python3.exe
s lying around - not very elegant. And it still doesn’t solve either of the other problems (PATH pollution and shebang ignorance).
In case this leaves you wondering, “why make a py
for Linux, then?” - that’s addressed, IMO, by the Windows documentation:
Unlike the PATH variable, the launcher will correctly select the most appropriate version of Python. It will prefer per-user installations over system-wide ones, and orders by language version rather than using the most recently installed version.
Linux can “select the most appropriate version of Python” natively (this is referring to shebang parsing). But even tricks like #!/usr/bin/env python
need additional work to “prefer per-user installations”. py
can keep track of them by other means besides the PATH. I believe (although I can’t test this right now) that it also allows overriding the script’s shebang preferences with the py
command line.
“Ordering by language version” is moot on Linux, because there’s only one python.exe
or python3.exe
to find, and it has already been configured to alias a specific minor version. But for example, on my system I have 3.8 that came with the OS, and 3.11 that I compiled from source and alt-installed into /usr/local/bin
; python
symlinks to python3
, which symlinks to 3.8, whereas a hypothetical py
would presumably default to 3.11 (assuming it knew about that installation). That would especially be useful on Linux because of the system dependence on Python - users would have an option to access the more recent version easily, while the system could use a system-tested version by just requesting python
and not needing to specify.