Running PP4E Examples on Python 3.3 through 3.6
The book Programming Python, 4th Edition (a.k.a. PP4E) was published when Python 3.2 was current. This page summarizes the 4 minor steps required to run this book's major examples with Python versions 3.3 through 3.6, and documents the corresponding changes applied to the current release 1.4 of the book's examples package, created October 15, 2013. In brief:
The first 2 of these steps are needed for Windows only, and the first 3 are incorporated into release 1.4 of the book's examples package automatically. For instance, with release 1.4 the PyGadgets and PyDemos auto-launchers, as well as the larger stand-alone programs such as PyMailGUI, PyEdit, and PyCalc will work on 3.3 through 3.6 out of the box. Still, you'll need to manually install Pillow instead of PIL for image processing examples such as PyPhoto, and may need to set your PY_PYTHON on Windows for general 3.X use.
Note that all these changes are backward-compatible with earlier 3.X releases, so release 1.4 of the book's examples package works with Pythons 3.0 through 3.6, and perhaps later. Later Pythons may or may not require additional patches; watch for updates to be posted here as warranted. Also note that most book examples will run unchanged under 3.3 through 3.6; the steps outlined here are mainly required for specific programs only, and mostly for larger graphical programs. Some minor examples may require other changes not given here, but change is a constant in software development.
As noted here, the new Windows launcher automatically installed with Python 3.3 runs scripts and commands with an installed 2.X by default, unless they give a more specific release number in #! patterns or command argument options. This can effectively break programs meant to be used with 3.X if they use generic Python commands or have top-level script files with missing or release-ambiguous #! lines. As it's common practice on Windows to omit a #! line formerly useful only in some Unix usage modes, this can have broad impacts. Even on Unix, #! lines with a generic "python" resolved by file links is a norm, but will now fail if run by Python 3.3 on Windows.
To work around this, you can either:
To work even in the absence of PY_PYTHON settings, release 1.4 of the examples package applies the required changes to the book's four auto-launcher scripts, plus one utility module that they leverage; the launchers see regular action as drug-out shortcuts on my Windows desktops:
Note that the last entry in this table, Launcher.py, sets PY_PYTHON=3 in os.environ, to be inherited by spawned programs. This may be moot for its immediate subprocesses, because this module runs explicit "python ..." command lines with os.spawnv() after setting Python and system paths automatically, thereby cutting out the 3.3 "py" launcher in the Windows registry; deeper program descendants, however, may still require this setting. Complex to be sure, but avoidable if you're willing to require an extra environment setting for using existing 3.X code under 3.3 on Windows, a manual task PP4E's top-level launchers were designed to obviate.
Also keep in mind that this patch applies to the selected auto-launcher scripts only. When using 3.3 and later, you'll still probably want to manually set your PY_PYTHON environment variable eventually in order to run other version-agnostic 3.X scripts on Windows with 3.X instead of 2.X. This includes any book examples not updated by this patch; see the Advanced system settings in your Control Panel's System entry to set the version default globally.
Although this patch suffices in the normal case, there are three issues that may impact your Windows launcher experience worth noting here:
c:\PP4E> type t.py #!/usr/bin/python3.3 import sys print(sys.version) c:\PP4E> t.py 3.2.2 (default, Sep 4 2011, 09:07:29) [MSC v.1500 64 bit (AMD64)] c:\PP4E> py t.py 3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:06:53) [MSC v.1600 64 bit (AMD64)]On another failer, this turns out even worse:
C:\PP4E> type t.py #!/usr/bin/python3 import sys print(sys.version) C:\PP4E> t.py 2.6 (r26:66721, Oct 2 2008, 11:35:03) [MSC v.1500 32 bit (Intel)] C:\PP4E> py t.py 3.4.0a2 (v3.4.0a2:9265a2168e2c+, Sep 8 2013, 19:41:05) [MSC v.1600 32 bit (Intel)]If the first command doesn't run the same highest-numbered 3.X Python installed and print the same version as the second, your associations are probably incorrect. In this case, the association reported by "assoc .py" and "ftype Python.File" command-line tools seem correct, but are apparently overridden by registry settings, and link to "python.exe" instead of "Python Launcher for Windows" in the Default Programs GUI.
For more on the 3.3 Windows launcher in general, see the new Appendix B in Learning Python, 5th Edition, or its early draft here. The often prescribed alternative to environment settings mentioned earlier—adding a Unix #! line at the top of every script on Windows—seems absurd and extreme, especially given other launcher issues like those of the former and following sections.
As described here, the new Windows launcher installed with Python 3.3 fails when a script begins with a Unix #! line that it cannot recognize. Some book example scripts used a "#!/bin/env python" pattern that was ignored on Windows by every Python through 3.2, but is now treated as an error by 3.3. Such #! forms are valid and even required on some Unix systems, but must be changed to a launcher-accepted pattern such as "#!/usr/bin/python" or "#!/usr/bin/env python" in order to run under 3.3 on Windows—a platform where such lines are otherwise irrelevant.
Note that this is true even if you use "python3" in the #! line or set your PY_PYTHON=3 per the prior section; an unrecognized #! pattern fails in 3.3 even if it's not version-ambiguous, and even if it's valid on a Unix system.
In release 1.4, this fix was applied to the #! lines at the top of the following 10 files, changing their "/bin/env" to "/usr/bin/env"; no other code or environment changes are required:
You can locate and edit these files yourself in older example packages by using the Search/Grep tool in the book's PyEdit GUI example on the package's PP4E root directory, or by running one of the directory search and edit/replace utilities presented in the System Programming part of the book (e.g., see search_all.py and Visitor subclasses later in Chapter 6). Fixing any additional unrecognized #! patterns lurking in the examples package is an officially suggested exercise.
For more on the 3.3 Windows launcher in general, see the new Appendix B in Learning Python, 5th Edition, or its early draft here.
As covered here, Python 3.3 changed a standard library email utility that the book's largest example, PyMailGUI, depends on to format non-ASCII email address names for display. The patch is simple, and spans just two files:
This is a small bit of "monkey-patching"—replacing part of a module at runtime—which should be avoided in general, but in this case suffices to make the existing code run as is. The changes required to fully support Python's email API changes since the book's publication would be much more involved.
The new and modified file of the patch are automatically included in PyMailGUI's source code directory of the new release 1.4 of the examples package; no other code or environment changes are required.
As mentioned here, the third-party PIL image-processing library used by examples in the book has been subsumed by the Pillow fork—an open source drop-in replacement for PIL which is being actively supported for use in newer Python releases. You'll want to fetch and install Pillow to use most of the book's image examples, including the PyPhoto viewer, which employs image display, thumbnail generation, and resize operations. I've also used Pillow successfully for EXIF photo metadata tag processing.
Pillow is currently
available at this site. For example, all
image-based book examples run fine under on Python 3.3 after installing the following on my
Windows 32- and 64-bit systems, respectively:
Also note that Pillow is not required of all image display-only programs: as of Python 3.4
tkinter can display PNG images (thanks to Tk 8.6), and all Python 3.X's can display GIF and
PPM/PPG images. Pillow is still required for other image type and Python combinations,
as well as for other tasks beyond display—including the thumbnail and resizing operations
implemented by PyPhoto.
No fix was applied, because the example package doesn't ship 3rd-party systems as bundled
items as a rule; you'll want to fetch and install Pillow for your Python and platform, from
its official site above.
In the book examples package
Also note that Pillow is not required of all image display-only programs: as of Python 3.4 tkinter can display PNG images (thanks to Tk 8.6), and all Python 3.X's can display GIF and PPM/PPG images. Pillow is still required for other image type and Python combinations, as well as for other tasks beyond display—including the thumbnail and resizing operations implemented by PyPhoto.
No fix was applied, because the example package doesn't ship 3rd-party systems as bundled items as a rule; you'll want to fetch and install Pillow for your Python and platform, from its official site above.