On 3/6/2011 7:07 AM, Michael Urman wrote:
I think Glenn Linderman hit the use cases on the head; I'm unclear why
he was against the overhead of a helper executable. The things I would
really want solutions for are these:
 * double click on a script, and have it launch the right python (2 or
3, w or not)
   * Probably scan for the final python[.\d]+ string and assume it's relevant.
 * be able to easily invoke python to interpret a script from the command prompt

I'd be comfortable with setting associations to a set of thin
executable wrappers which examined the #! line to extract a python
version. 

I'm only against the overhead of a helper written in Python, since it would have to launch Python (some explicit version) to run the helper script, and then launch the "right" version of Python to execute the real script.  You mention a thin executable wrapper, and I have no problem with the overhead of that, probably.

Seems that the PEP addresses two sub problems on Unix created by the coexistence of multiple incompatible major versions of Python:

(1) how to invoke the right version of the interactive Python from the command line, and
(2) how to specify the right version of Python inside Python scripts. 

One solution solves both problems on Unix... the declaration that /usr/bin/python (generally on the PATH and invocable from the shell as  python) may be an installation dependent version, and the creation of appropriate version specific links and/or binaries for specific major and/or minor versions, to be used either from the command line or the #! line of scripts.

For Windows, it is true at present that neither of the above problems has a solution:
(1) a fully qualified installation path name must be used to invoke any version of Python, since it is not on the PATH
(2) Only the last installed version of Python will be invoked by launching a Python script name something-or-another.py

Hence, omitting Windows behaviors from the PEP leaves Windows without a solution for either problem, no worse off than it was before, but neither is it better off.

If the PEP wants to address (1) interactive launching from the command line on Windows, that could be done by placing a batch file in System32; providing versioned symlinks in installed on a file system that supports them, or providing versioned binaries on a file system that doesn't support symlinks, either in System32, or by adding the Python installation directory to the PATH.  For interactive use, most of these solutions are roughly equivalent in function.

Since Windows does not use a #! line, then the solutions for (2) must be different.  The ones that I can think of are:

(A) declare the Python version in the name of the script file.  By doing so in the extension, additional Windows associations could be created to launch different versions of Python.  Switching versions would be as simple as renaming the file, changing the extension to include a different version.  However, various tools would have to learn about additional extensions that mean Python (syntax directed editors, etc.)  And it would be hard to have a script in a module, unless the importer recognized all those extensions too.  So this "solution" has ripple effects that make it unattractive, although it is simple to implement the basic feature.

(B) declare the Python version in the content of the script file.  This cures most of the ripple effects of the above, but requires a "launcher" or "wrapper" program to be designed, implemented, and installed.  There are a variety of subsolutions for different ways of declaring the version.

(B1) Use the Unix #! line, and attempt to parse the version from it.  This assumes there is a Unix #! line, note that Windows-only scripts wouldn't need them in the first place.  Looking at and interpreting the Unix #! line, and translating it into an invocation of Python on Windows is clever and doable, but very tightly tied to Python.

(B2) Use a second #! line, and attempt to parse a whole command from it, using Windows pathname syntax.  This is attractive for cross-platform script, and builds on the Unix #! line which is well-understood by Unix and cross-platform developers.  Again, Windows-only scripts wouldn't need a Unix #! line, but if this solution uses a second one, then the first must be created, possibly empty.  Also, if there are parameters the script needs that only apply to one platform, they could be placed in the appropriate platform's #! line.

(B3) Invent a variant syntax for #! -- perhaps #@.  Since it is different than #!, it could be on the first line, if no Unix #! line is needed, but if not found on the first line, the second line would be examined, to allow #! on the first line for a cross-platform script.  Same costs/benefits as (B2).

(B4) As a variation on (B2) or (B3), the declaration of the version would not have to be a command line format... it could be   "#@ Version 3.2", as it is purely up to the launcher/wrapper program to interpret it.  This complicates the wrapper script, as it would have to examine the registry to find the particular location of Python, and tightly binds it to Python usage only.


I like (B3) best, now that I've thought of it, although I implemented a form of (B2) in a private copy of http.server so I could have a cross-platform CGI script.

(B2) and (B3) also allow the wrapper to be configured to work for similar things for other scripting languages, which also have cross-platform problems similar to Python.  All the user would have to do is put the extra #!/#@ line in, and associate that extension with the wrapper.

By default, for Python, the wrapper would get associated only with .py files.