The new Windows launcher, shipped and installed automatically with Python 3.3 (and presumably later), and available as a standalone package for use with other versions, addresses these deficits in the former install model by providing two new executables:
py.exe for console programs
pyw.exe for nonconsole (typically GUI) programs
These two programs are registered to open .py and .pyw files, respectively, via Windows filename associations. Like Python’s original python.exe main program (which they do not deprecate but can largely subsume), these new executables are also registered to open byte code files launched directly. Amongst their weapons, these two new executables:
Automatically open Python source and byte-code files launched by icon clicks or filename commands, via Windows associations
Are normally installed on your system search path and do not require a directory path or PATH settings when used as command lines
Allow Python version numbers to be passed in easily as command-line arguments, when starting both scripts and interactive sessions
Attempt to parse Unix-style #! comment lines at the top of scripts to determine which Python version should be used to run a file’s code
The net effect is that under the new launcher, when multiple Pythons are installed on Windows, you are no longer limited to either the latest version installed or explicit/full command lines. Instead, you can now select versions explicitly on both a per-file and per-command basis, and specify versions in either partial or full form in both contexts. Here’s how this works:
To select versions per file, use Unix-style top-of-script comments like these:
#!python2 |
#!/usr/bin/python2.7 |
#!/usr/bin/env python3 |
To select versions per command, use command lines of the following forms:
py −2 m.py |
py −2.7 m.py |
py −3 m.py |
For example, the first of these techniques can serve as a sort of directive to declare which Python version the script depends upon, and will be applied by the launcher whenever the script is run by command line or icon click (these are variants of a file named script.py):
#!python3 ... ...a 3.X script# Runs under latest 3.X installed ... #!python2 ... ...a 2.X script# Runs under latest 2.X installed ... #!python2.6 ... ...a 2.6 script# Runs under 2.6 (only) ...
On Windows, command lines are typed in a Command Prompt window, designated by its C:\code> prompt in this appendix. The first of the following is the same as both the second and an icon click, because of filename associations:
C:\code>script.py# Run per file's #! line if present, else per default C:\code>py script.py# Ditto, but py.exe is run explicitly
Alternatively, the second technique just listed can select versions with argument switches in command lines instead:
C:\code>py −3 script.py# Runs under latest 3.X C:\code>py −2 script.py# Runs under latest 2.X C:\code>py −2.6 script.py# Runs under 2.6 (only)
This works both when launching scripts and starting the interactive interpreter (when no script is named):
C:\code>py −3# Starts latest 3.X, interactive C:\code>py −2# Starts latest 2.X, interactive C:\code>py −3.1# Starts 3.1 (only), interactive C:\code>py# Starts default Python (initially 2.X: see ahead)
If there are both #! lines in the file and a version number switch in the command line used to start it, the command line’s version overrides that in the file’s directive:
#! python3.2 ... ...a 3.X script... C\code>py script.py# Runs under 3.2, per file directive C\code>py −3.1 script.py# Runs under 3.1, even if 3.2 present
The launcher also applies heuristics to select a specific Python version when it is missing or only partly described. For instance, the latest 2.X is run when only a 2 is specified, and a 2.X is preferred for files that do not name a version in a #! line when launched by icon click or generic command lines (e.g., py m.py, m.py), unless you configure the default to use 3.X instead by setting PY_PYTHON or a configuration file entry (more on this ahead).
Especially in the current dual 2.X/3.X Python world, explicit version selection seems a useful addition for Windows, where many (and probably most) newcomers get their first exposure to the language. Although it is not without potential pitfalls—including failures on unrecognized Unix #! lines and a puzzling 2.X default—it does allow for a more graceful coexistence of 2.X and 3.X files on the same machine, and provides a rational approach to version control in command lines.
For the complete story on the Windows launcher, including more advanced features and use cases I’ll either condense or largely omit here, see Python’s release notes and try a web search to find the PEP (the proposal document). Among other things, the launcher also allows selecting between 32- and 64-bit installs, specifying defaults in configuration files, and defining custom #! command string expansion.