GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||
GeezerVison is showing learning-python.com — The New Windows Launcher in Python 3.3
October 2012 (updated July 2018) The New Windows Launcher in Python 3.3This page describes the new Windows launcher for Python, installed automatically with Python 3.3 and later, and available separately on the Web for use with older versions. The new launcher provides an extra layer of code that chooses and starts an installed Python. Though it comes with some pitfalls, it provides some much-needed coherence for program execution when multiple Pythons coexist on the same computer. I've written this page for programmers using Python on Windows. Though it's platform-specific by nature, it's targeted at both Python beginners (most of whom get started on this platform), as well as Python developers who write code to work portably between Windows and Unix. As we'll see, the new launcher changes the rules on Windows radically enough to impact everyone who uses Python on Windows, or may in the future. The Unix Legacy
To fully understand the launcher's protocols, we have to begin
with a short history lesson. Unix developers long ago devised
a protocol for designating a program to run a script's code.
On Unix, the first line in a script's text file is special if it
begins with the two characters
In Unix scripts, such lines designate a program to run the rest
of the script's code, by coding it after the #!/usr/local/bin/python ...script's code # run under this specific program #!/usr/bin/env python ...script's code # run under "python" found on PATHBy making such a script executable (e.g., via chmod +x script.py),
it can be run by giving just its filename in a command line; the
#! line at the top then directs the Unix shell to a program which
will run the rest of the file's code. Depending on the platform's
install structure, the python which these #! lines name might
be a real executable, or a symbolic link to a version-specific
executable located elsewhere. These lines might also name a more
specific executable explicitly, such as python3. Either way,
by changing #! lines, symbolic links, or PATH settings,
Unix developers can route a script to the appropriate installed
Python.
None of this applies to Windows itself, of course, where The Windows LegacyThe install model has been very different on the other side of the fence. In the past (well, in every Python until 3.3), Windows installs updated the global Windows registry such that the latest Python version installed on your computer was the version that opened Python files when they were clicked or run by direct filename in command lines. Some Windows users may know this registry as filename associations, configurable in Control Panel's Default Programs dialog.
Under this install model, if you wished to open a file with a
different version than the latest install, you had to run a
command line giving the full path to the Python you wanted, or
update your filename associations manually to use the desired version.
You could also point generic
This reflects the natural model on Windows (when you click on a
Introducing the New Windows LauncherThe new Windows launcher, installed automatically with Python 3.3 and available as a stand-alone package for use with other versions, addresses these deficits in the former install model by providing two new executables:
.py and .pyw files, respectively
via Windows filename associations. Like Python's original python.exe
main program (which they do not deprecate, but automatically spawn and can largely subsume),
these new executables are also registered to open bytecode files launched directly.
Amongst their weapons, these two new executables:
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:
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: #!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:\temp> prompt in this document. The first
of the following is the same as both the second and an icon click,
because of filename associations:
C:\temp> script.py # run per file's #! line if present, else per default C:\temp> py script.py # ditto, but py.exe is run explicitlyAlternatively, the second technique listed above can select versions with argument switches in command lines instead: C:\temp> py -3 script.py # runs under latest 3.X C:\temp> py -2 script.py # runs under latest 2.X C:\temp> py -2.6 script.py # runs under 2.6 (only)This works both when launching scripts, and when starting the interactive interpreter (when no script is named): C:\temp> py -3 # starts latest 3.X, interactive C:\temp> py -2 # starts latest 2.X, interactive C:\temp> py -3.1 # starts 3.1 (only), interactive C:\temp> py # start 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\temp> py script.py # runs under 3.2, per file directive C\temp> py -3.1 script.py # runs under 3.1, even if 3.2 presentThe 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
the default is configured 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
For more on the Windows launcher, including more advanced features and
use cases I'll either condense or largely omit here, see
this, and
this. Among other
things, the launcher also allows selecting between 32- and 64-bit installs,
specifying defaults in configuration files, and defining custom A Windows Launcher TutorialSome readers familiar with Unix scripting may find the prior section enough to get started. For others, this section provides additional context in the form of a tutorial, which gives concrete examples of the launcher in action for you to trace through. This section also discloses additional launcher details along the way, though, so even well-seasoned Unix veterans may benefit from a quick scan here before FTPing all their Python scripts to the local Windows box.
To get started, we'll be using the following simple script, #!python3 import sys print(sys.version.split()[0]) # first part of stringThis script's first-line comment serves to designate the required Python version; it must begin with #! per Unix convention, and
allows for a space before the python3 or not.
On my machine I currently have 2.7, 3.1, 3.2, and 3.3 all
installed; let's watch which version is invoked as the
script's first line is modified in the following sections,
exploring file directives, command lines, and defaults along the way.
Step 1: Using Version Directives in Files
As this script is coded, when run by icon click or command line, the first
line directs the registered #! python3 import sys print(sys.version.split()[0]) C:\temp> what.py # run per file directive 3.3.0 C:\temp> py what.py # ditto: latest 3.X 3.3.0Again, the space after #! is optional; I added a space to
demonstrate the point here. Note that the first what.py command
here is equivalent to both an icon click and py what.py, because
the py.exe program is registered to open .py files automatically
in the Windows filename-associations registry when the launcher is
installed.
Also note that when launcher documentation talks about the "latest" version,
it means the highest-numbered version. That is, it refers to the latest
released, not the latest installed on your computer (if you install 3.1
after 3.3,
Now, changing the first line to name to #! python2 ...rest of script unchanged C:\temp> what.py # run with latest 2.X per #! 2.7.3And you can request a more specific version if needed—for example, if you don't want the latest in a Python line: #! python3.1 ... C:\temp> what.py # run with 3.1 per #! 3.1.4This is true even if the requested version is not installed—which is treated as an error case by the launcher: #! python2.6 ... C:\temp> what.py Requested Python version (2.6) is not installedUnrecognized Unix #! lines are also treated as errors, unless
you give a version number as a command-line switch to compensate,
as the next section describes in more detail (and as the section
on launcher issues will revisit as a pitfall):
#!/bin/python ... C:\temp> what.py Unable to create process using '/bin/python "C:\temp\what.py" ' C:\temp> py what.py Unable to create process using '/bin/python what.py' C:\temp> py -3 what.py 3.3.0Technically, the launcher recognizes Unix-style #! lines at
the top of script files which follow one of the following four
patterns:
#!/usr/bin/env python* #!/usr/bin/python* #!/usr/local/bin/python* #!python*Any #! line that does not take one of these recognized and
parseable forms is assumed to be a fully specified command line
to start a process to run the file, which is passed to Windows
as is, and generates the error message we saw previously if not
a valid Windows command.
(The launcher also supports "customized" command expansions via its
configuration files which are attempted before passing unrecognized
commands on to Windows, but we'll gloss over these here.)
In recognizable
#! line at all behave the same as those that name just
a generic python, the omitted case above, and are influenced by PY_PYTHON
default settings. The first case, partials, may also be affected by
version-specific environment settings (e.g. PY_PYTHON3=3.1 to select
3.1 for python3, and PY_PYTHON2=2.6 to pick 2.6 for python2).
We'll revisit defaults later in this tutorial.
First, though, note that anything after the #!python3 [any python.exe arguments go here] ...But this leads us to launcher command lines in general, and will suffice as a natural segue to the next section. Step 2: Using Command-Line Version Switches
As mentioned, version switches on command lines can be used to
select a Python version if one isn't present in the file. You
run a # not a launcher directive ... C:\temp> py -3 what.py # run per command-line switch 3.3.0 C:\temp> py -2 what.py # ditto: latest 2.X installed 2.7.3 C:\temp> py -3.2 what.py # ditto: 3.2 specifically (and only) 3.2.3 C:\temp> py what.py # run per launcher's default (ahead) 2.7.3But command-line switches also take precedence over a version designation in a file's directive: #! python3.1 ... C:\temp> what.py # run per file directive 3.1.4 C:\temp> py what.py # ditto 3.1.4 C:\temp> py -3.2 what.py # switches override directives 3.2.3 C:\temp> py -2 what.py # ditto 2.7.3Formally, the launcher accepts the following command-line argument types (which exactly mirror the * part at the end of
a file's #! line described in the prior section):
-2 Launch the latest Python 2.X version -3 Launch the latest Python 3.X version -X.Y Launch the specified Python version -X.Y-32 Launch the specified 32-bit Python versionAnd the launcher's command lines take the following general form: py [py.exe arg] [python.exe args] script.py [script.py args]Anything following the launcher's own argument (if present) is treated as though it were passed to the python
program—typically, this includes any arguments for Python itself,
followed by the script filename, followed by any arguments meant
for the script, though the usual -m mod, -c cmd, and - program
specification forms work in a py command line too (as mentioned
earlier, arguments to python.exe can also appear at the end of the
#! directive line in a file, if used).
Let's write a new script which extends the prior with argument display
to trace; # args.py, show my arguments too import sys print(sys.version.split()[0]) print(sys.argv) C:\temp> py -3 -i args.py -a 1 -b -c # -3: py, -i: python, rest: script 3.3.0 ['args.py', '-a', '1', '-b', '-c'] >>> ^Z C:\temp> py -i args.py -a 1 -b -c # args to python, script 2.7.3 ['args.py', '-a', '1', '-b', '-c'] >>> ^Z C:\temp> py -3 -c print(99) # -3 to py, rest to python: "-c cmd" 99 C:\temp> py -2 -c "print 99" 99Notice how the first two launches above run the default Python unless a version is given in the command line, because no #! line
appears in the script itself. Somewhat coincidentally, that leads
us to the last topic of this tutorial.
Step 3: Using and Changing Defaults
As also mentioned, the launcher defaults to 2.X for a
generic #!python ... # same as #!/usr/bin/python C:\temp> what.py # run per launcher default 2.7.3The default is also applied when no directive is present at all—perhaps the most common case for code written to be used on Windows primarily or exclusively: # not a launcher directive ... C:\temp> what.py # also run per default 2.7.3 C:\temp> py what.py # ditto 2.7.3But you can set the launcher's default to 3.X with initialization-file or environment-variable settings, which will apply to both files run from command lines and by icon clicks via their name's association with py.exe or pyw.exe in the Windows registry:
# not a launcher directive ... C:\temp> what.py # run per default 2.7.3 C:\temp> set PY_PYTHON=3 # or via Control Panel/System C:\temp> what.py # run per changed default 3.3.0 As suggested earlier, for more fine-grained control you can also set version-specific environment variables to direct partial selections to a specific release, instead of falling back on the release with highest minor number installed: #!python3 ... C:\temp> py what.py # runs "latest" 3.X 3.3.0 C:\temp> set PY_PYTHON3=3.1 # use PY_PYTHON2 for 2.X C:\temp> py what.py # override highest-minor choice 3.1.4
Making such settings in the Control Panel's System window
will make them apply globally across your machine. You
may or may not want to set defaults this way, depending
on the majority of the Python code you'll be running.
Many Python 2.X users can probably rely on defaults unchanged,
and override them in However, the setting used for directive-less files, PY_PYTHON, seems fairly crucial. Most programmers who have used Python on Windows in the past will probably expect 3.X to be the default after installing 3.3, especially given that the launcher is installed by 3.3 in the first place!—a seeming paradox, which leads us to the next section. Update: 2016's Python 3.6 eventually changed the default to be Python 3.X—but only in some contexts, and only for code run on 3.6 and later. Read about the bifurcation here. Pitfalls of the New Windows LauncherThough the new Windows launcher in 3.3 is a nice addition, like much in 3.X it may have been nicer had it appeared years ago. Unfortunately, it comes with some backward incompatibilities which may be an inevitable byproduct of today's multi-version Python world, but which may break some existing programs. This includes examples in book's I've written, and probably many others. While porting code to 3.3, I've come across three launcher issues worth noting:
Pitfall 1: Unrecognized Unix !# Lines Now Make Scripts Fail on Windows
The new Windows launcher recognizes Unix
More generally, scripts with any
Unix-style Book Examples Impact and Fix
With respect to the book examples I ported to 3.3, this broke roughly a dozen
scripts that started with
One open issue here:
strangely, passing any command-line switch to the launcher,
even a Pitfall 2: The Launcher Defaults to Using 2.X Unless Told Otherwise
Oddly, the Windows 3.3 launcher defaults to using an installed Python 2.X
when running scripts that don't select 3.X explicitly. That is, scripts which
either have no
The implications of this are potentially broad. As one example, clicking
the icon of a directive-less 3.X file just after installing 3.3 may now fail,
because the associated launcher assumes you mean to use 2.X by default.
This probably won't be a pleasant first encounter for some Python newcomers!
This assumes the 3.X file has no
Program launches which don't give an explicit version number might be arguably
ambiguous on Unix too, and often rely on symbolic links from Book Examples Impact and Fix
In terms of my book examples port, this 2.X default caused multiple 3.X script
failures after installing 3.3, for both scripts with no Update: see also the earlier note about launcher-default changes in 2016's Python 3.6; it's a partial fix. Pitfall 3: The New PATH Extension is Off by Default and Seems Contradictory
Besides installing the new launcher, the Windows Python 3.3 installer
can automatically add the directory containing 3.3's
As described, the new launcher's
Also note that updating your Conclusions: a Net Win for WindowsTo be fair, some of the prior section's pitfalls may be an inevitable consequence of trying to simultaneously support a Unix feature on Windows and multiple installed versions. In exchange, it provides a coherent way to manage mixed-version scripts and installations. You'll probably find the Windows launcher shipped with 3.3 and later to be a major asset once you start using it, and get past any initial incompatibilities you may encounter.
In fact, you may also want to start getting into the habit of coding
compatible Unix-style
But you should be aware that the launcher may break some formerly
valid scripts with For More ReadingThis page's material was revised and published in this book, which has more on using Python on Windows and elsewhere. There was also a minor update to the Windows-launcher story in 2016's Python 3.6, described here. For additional reading, try these other articles popular at learning-python.com:
These and more are available on the blog page. | ||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |