[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Proper shebang for python3

On 7/20/19, Michael Speer <knomenet at gmail.com> wrote:
> You may want to use `#!/usr/bin/env python3` instead.

This is partially supported in Windows, but only if .py files are
associated with the py.exe launcher and the shebang runs "python"
instead of "python3".

py.exe supports four builtin virtual commands: "/usr/bin/env python",
"/usr/bin/python", "/usr/local/bin/python", and "python". The "python"
command can be qualified with a version specification of the form
"X[.Y][-32|-64]", such as "python3". The "/usr/bin/env python" virtual
command searches PATH, but only if the command matches "python"
exactly. If there's a version specified, or if it's not an "env"
virtual command, the launcher looks for a registered Python
installation instead of searching PATH.

For all other commands, the launcher skips a virtual Unix prefix (i.e.
"/usr/bin/env", "/usr/bin", and "/usr/local/bin"), if present, and
searches PATH. For example, given "/usr/bin/pypy", it searches PATH
for "pypy" plus the file extensions in PATHEXT (i.e. .COM, .EXE, etc).
If the command isn't found in PATH, it checks in the "[commands]"
section of "%LocalAppData%\py.ini". For example, py.ini could define

A virtual environment should have a "python" executable, so shebangs
that use "/usr/bin/env python" will prefer an active virtual
environment. But a lot of scripts use "python3" instead of "python".
This is a stumbling block in Windows since we don't install versioned
"pythonX[.Y].exe" binaries. Thus the "env" virtual command is special
cased to find a qualified Python version in the list of registered
Python installations instead of searching PATH. (The new store app
distribution does install versioned app links, but, even in this case,
virtual environments lack versioned binaries in the "Scripts"

That said, some developers manually create versioned binaries as
symlinks, hardlinks, or copies. Also, maybe a future version of the
full (non-app) Python installation will do the same. Thus I think the
launcher should search PATH for all "/usr/bin/env python*" shebangs,
but without the binary-type specification (i.e. "-32" or "-64") if
present. In this case, instead of a regular search based on WINAPI
SearchPath, we'll need a custom search that tokenizes and walks PATH
and checks the binary type via GetBinaryTypeW. If no matching version
is found in PATH, the "env" search should fall back on the list of
registered versions.