Though 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 multiversion Python world, but which may also break some existing programs. This includes examples in books I’ve written, and probably many others. While porting code to 3.3, I’ve come across three launcher issues worth noting:
Unrecognized Unix !# lines now make scripts fail on Windows.
The launcher defaults to using 2.X unless told otherwise.
The new PATH extension is off by default and seems contradictory.
The rest of this section gives a rundown of each of these three issues in turn. In the following, I use the programs in my book Programming Python, 4th Edition, as an example to illustrate the impacts of launcher incompatibilities, because porting these 3.1/3.2 examples to 3.3 was my first exposure to the new launcher. In my specific case, installing 3.3 broke numerous book examples that worked formerly under 3.2 and 3.1. The causes for these failures outlined here may break your code too.
The new Windows launcher recognizes Unix #! lines that begin with #!/usr/bin/env python but not the other common Unix form #!/bin/env python (which is actually mandated on some Unixes). Scripts that use the latter of these, including some of my book examples, worked on Windows in the past because their #! lines coded for Unix compatibility have been ignored as comments by all Windows Pythons to date. These scripts now fail to run in 3.3 because the new launcher doesn’t recognize their directive’s format and posts an error message.
More generally, scripts with any #! Unix line not recognized will now fail to run on Windows. This includes scripts having any first line that begins with a #! that is not followed by one of the four recognized patterns described earlier: /usr/bin/env python*, /usr/bin/python*, /usr/local/bin/python*, or python*. Anything else won’t work, and requires code changes. For instance, a somewhat common #!/bin/python line also causes a script to now fail on Windows, unless a version number is given in command-line switches.
Unix-style #! lines probably aren’t present in Windows-only programs, but can be common in programs meant to be run on Unix too. Treating unrecognized Unix directives as errors on Windows seems a bit extreme, especially given that this is new behavior in 3.3, and will likely be unexpected. Why not just ignore unrecognized #! lines and run the file with the default Python—like every Windows Python to date has? It’s possible that this might be improved in a future 3.X release (there may be some pushback on this), but today you must change any files using a #!/bin/env or other unrecognized pattern, if you want them to run under the launcher installed with Python 3.3 on Windows.
With respect to the book examples I ported to 3.3, this broke roughly a dozen scripts that started with #!/bin/env python. Regrettably, this includes some of the book’s user-friendly and top-level demo launcher scripts (PyGadgets and PyDemos). To fix, I changed these to use the accepted #!/usr/bin/env python form instead. Altering your Windows file associations to omit the launcher altogether may be another option (e.g., associating .py files with python.exe instead of py.exe), but this negates the launcher’s benefits, and seems a bit much to ask of users, especially newcomers.
One open issue here: strangely, passing any command-line switch to the launcher, even a python.exe argument, seems to negate this effect and fall back on the default Python—m.py and py m.py both issue errors on unrecognized #! lines, but py -i m.py runs such a file with the default Python. This seems a possible launcher bug, but also relies on the default, the subject of the next issue.
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 that either have no #! directive or use one that names python generically will be run by a 2.X Python by default when launched by icon clicks, direct filename command lines (m.py), or launcher command lines that give no version switch (py m.py). This is true even if 3.3 is installed after a 2.X on your machine, and has the potential to make many 3.X scripts fail initially.
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 #! directive that provides an explicit python3 version number, but most scripts meant to run on Windows won’t have a #! line at all, and many files coded before the launcher came online won’t accommodate its version number expectations. Most 3.X users will be basically compelled to set PY_PYTHON after installing 3.3—hardly a usability win.
Program launches that don’t give an explicit version number might be arguably ambiguous on Unix too, and often rely on symbolic links from python to a specific version (which is most likely 2.X today—a state the new Windows launcher seems to emulate). But as for the prior issue, this probably shouldn’t trigger a new error on Windows in 3.3 for scripts that worked there formerly. Most programmers wouldn’t expect Unix comment lines to matter on Windows, and wouldn’t expect 2.X to be used by default just after installing 3.X.
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 #! line, as well as scripts with a Unix-compatible #!/usr/bin/python line. To fix just the latter, change all scripts in this category to name python3 explicitly instead of just python. To fix both the former and the latter in a single step, set the Windows launcher’s default to be 3.X globally with either a py.ini configuration file (see the launcher’s documentation for details) or a PY_PYTHON environment variable setting as shown in the earlier examples (e.g., set PY_PYTHON=3). As mentioned in the prior point, manually changing your file associations is another solution, but none of these options seem simpler than those imposed by prior install schemes.
Besides installing the new launcher, the Windows Python 3.3 installer can automatically add the directory containing 3.3’s python.exe executable to your system PATH setting. The reasoning behind this is that it might make life easier for some Windows beginners—they can type just python instead of the full directory path to it. This isn’t a feature of the launcher per se, and shouldn’t cause scripts to fail in general. It had no impact on the book examples. But it seems to clash with the launcher’s operation and goals, and may be best avoided. This is a bit subtle, but I’ll explain why.
As described, the new launcher’s py and pyw executables are by default installed on your system search path, and running them requires neither directory paths nor PATH settings. If you start scripts with py instead of python command lines, the new PATH feature is irrelevant. In fact, py completely subsumes python in most contexts. Given that file associations will launch py or pyw instead of python anyhow, you probably should too—using python instead of py may prove redundant and inconsistent, and might even launch a version different than that used in launcher contexts should the two schemes’ settings grow out of sync. In short, adding python to PATH seems contradictory to the new launcher’s worldview, and potentially error-prone.
Also note that updating your PATH assumes you want a python command to run 3.3 normally, and this feature is disabled by default; be sure to select this in the install screen if you want this to work (but not if you don’t!). Due to the second pitfall mentioned earlier, many users may still need to set PY_PYTHON to 3 for programs run by icon clicks that invoke the new launcher, which seems no simpler than setting PATH, a step that the launcher was meant to remove. You may be better served by using just the launcher’s executables, and changing just PY_PYTHON as needed.