new version of pep-0397 based on python-dev feedback
This commit is contained in:
parent
3acd94ec7f
commit
0abda1e625
290
pep-0397.txt
290
pep-0397.txt
|
@ -7,7 +7,7 @@ Status: Draft
|
|||
Type: Standards Track
|
||||
Content-Type: text/plain
|
||||
Created: 15-Mar-2011
|
||||
|
||||
Post-History: 17-May-2011, 15-Mar-2011
|
||||
|
||||
Abstract
|
||||
|
||||
|
@ -67,8 +67,8 @@ Rationale
|
|||
An overview of the launcher.
|
||||
|
||||
This PEP outlines the general functionality and key guidelines of a
|
||||
launcher for Windows. It is accompanied by reference implementation,
|
||||
written in Python, which defines the detailed implementation. Over
|
||||
launcher for Windows. It is accompanied by a reference implementation
|
||||
[3], written in Python, which defines the detailed implementation. Over
|
||||
time, changes to the implementation may be desired - if the changes
|
||||
adhere to the guidelines in this PEP and have been made following
|
||||
the standard Python development model this PEP need not change.
|
||||
|
@ -141,16 +141,15 @@ Guidelines for a Python launcher.
|
|||
feature offered by Unix and would be useful for Windows users in
|
||||
some cases.
|
||||
|
||||
The launcher should be capable of supporting implementations other
|
||||
than CPython, such as jython and IronPython. In particular, if there
|
||||
are common symbolic links used on Unix to specify such an
|
||||
implementation (such as "/usr/bin/jython"), the launcher need not
|
||||
support such references on Windows. However, if there is strong desire
|
||||
from the community to support these other implementations in a Windows
|
||||
specific way, any such proposals will be judged on their merit. Even
|
||||
without specialized support for these alternate implementations, the
|
||||
ability to specify the fully-qualified path to an executable could be
|
||||
used as a fallback.
|
||||
The launcher will be capable of supporting implementations other than
|
||||
CPython, such as jython and IronPython, but given both the absence of
|
||||
common links on Unix (such as "/usr/bin/jython") and the inability for the
|
||||
launcher to automatically locate the installation location of these
|
||||
implementations on Windows, the launcher will support this via
|
||||
customization options. Scripts taking advantage of this will not be
|
||||
portable (as these customization options must be set to reflect the
|
||||
configuration of the machine on which the launcher is running) but this
|
||||
ability is nonetheless considered worthwhile.
|
||||
|
||||
On Unix, the user can control which specific version of Python is used
|
||||
by adjusting the links in /usr/bin to point to the desired version. As
|
||||
|
@ -160,76 +159,155 @@ Guidelines for a Python launcher.
|
|||
"/usr/bin/python2" will automatically locate a Python 2.x implementation,
|
||||
an environment variable can override exactly which Python 2.x
|
||||
implementation will be chosen. Similarly for "/usr/bin/python" and
|
||||
"/usr/bin/python3".
|
||||
|
||||
While the guidelines above are general, the launcher should make
|
||||
concessions for any Windows specific issues which increase the
|
||||
usefulness of the launcher on Windows. In other words, the
|
||||
guidelines above will not prevent Windows specific functionality
|
||||
which makes the launcher significantly more useful for Windows
|
||||
users.
|
||||
"/usr/bin/python3". This is specified in detail later in this PEP.
|
||||
|
||||
Shebang line parsing
|
||||
|
||||
If the first command-line argument does not start with a dash ('-')
|
||||
character, an attempt will be made to open that argument as a file
|
||||
and parsed for a shebang line according to the rules in [1]. Once
|
||||
parsed, the command will be examined to see if it is a "virtual
|
||||
command". A virtual command starts with either of the strings
|
||||
'/usr/bin/python', '/usr/bin/env python' or 'python' - while the
|
||||
latter will not work on Unix, it will be offered as a convenience
|
||||
for Windows users not familiar with the Unix conventions and with no
|
||||
desire to have the shebang line work on Unix.
|
||||
parsed, the command will be categorized according to the following rules:
|
||||
|
||||
Commands which are virtual are not treated as containing a file-system
|
||||
path, but instead are treated as references to an installed Python.
|
||||
Optionally, the virtual command may include a specific version, such
|
||||
as '/usr/bin/python2' or '/usr/bin/python3.2'. If only a "major version"
|
||||
qualifier is found, the launcher will enumerate the installed Python
|
||||
versions and use the latest minor release found for the major version,
|
||||
which is likely, although not guaranteed, to be the most recently
|
||||
installed version in that family. If major and minor version qualifiers
|
||||
are found, that specific version will be located and used.
|
||||
* If the command starts with the definition of a customized command
|
||||
followed by a space character, the customized command will be used.
|
||||
See below for a description of customized commands.
|
||||
|
||||
If a virtual command has no version specifier, or if no shebang line
|
||||
is found, the launcher will attempt to locate a Python 2.x
|
||||
installation and use the latest found. If none are found, it will
|
||||
attempt to use the latest Python 3.x implementation found.
|
||||
* If the command starts with the strings '/usr/bin/python',
|
||||
'/usr/bin/env python' or 'python' the command will be treated as a
|
||||
'virtual command' and the rules described in Python Version Qualifiers
|
||||
(below) will be used to locate the executable to use.
|
||||
|
||||
* Otherwise the command is assumed to be directly ready to execute - ie.
|
||||
a fully-qualified path optionally followed by arguments. The contents
|
||||
of the string will not be parsed - it will be passed directly to the
|
||||
Windows CreateProcess function after appending the name of the script
|
||||
and the launcher command-line arguments. This means that the rules used
|
||||
by CreateProcess will be used, including how relative path names and
|
||||
executable references without extensions are treated. Notably, the
|
||||
Windows command processor will not be used, so special rules used by the
|
||||
command processor (such as automatic appending of extensions other than
|
||||
'.exe', support for batch files, etc) will not be used.
|
||||
|
||||
The use of 'virtual' shebang lines will be encouraged as this should
|
||||
allow for portable shebang lines to be specified which work on
|
||||
multiple operating systems.
|
||||
|
||||
If the shebang line is not a virtual one as described above, it is
|
||||
assumed to be a path to an executable - presumably a Python
|
||||
executable, but this will not be checked. No version qualifiers are
|
||||
parsed - if a specific version is required, then the path should
|
||||
reflect that. Relative path specifications will be considered
|
||||
relative to the directory of the launcher. Thus, a shebang line of
|
||||
'#! python' will look for a python executable in the same directory
|
||||
as the launcher.
|
||||
|
||||
Non-virtual shebang lines should be discouraged as they make the
|
||||
script specific to a specific Windows installation. However, they
|
||||
are supported for maximum flexibility.
|
||||
multiple operating systems and different installations of the same
|
||||
operating system.
|
||||
|
||||
If the first argument can not be opened as a file or if no valid
|
||||
shebang line can be found, a default Python interpreter will be
|
||||
shebang line can be found, the launcher will act as if a shebang line of
|
||||
'!#python' was found - ie., a default Python interpreter will be
|
||||
located and the arguments passed to that. However, if a valid
|
||||
shebang line is found but the process specified by that line can not
|
||||
be started, the default interpreter will not be started - the error
|
||||
to create the specified child process will be considered fatal and
|
||||
the launcher will display an appropriate message and terminate with
|
||||
a specific exit code.
|
||||
to create the specified child process will cause the launcher to display
|
||||
an appropriate message and terminate with a specific exit code.
|
||||
|
||||
Virtual commands in shebang lines:
|
||||
|
||||
Virtual Commands are shebang lines which start with the strings
|
||||
'/usr/bin/python', '/usr/bin/env python' or 'python'. Optionally, the
|
||||
virtual command may be suffixed with a version qualifier (see below),
|
||||
such as '/usr/bin/python2' or '/usr/bin/python3.2'. The command executed
|
||||
is based on the rules described in Python Version Qualifiers below.
|
||||
|
||||
Customized Commands:
|
||||
|
||||
The launcher will support the ability to define "Customized Commands" in a
|
||||
Windows .ini file (ie, a file which can be parsed by the Windows function
|
||||
GetPrivateProfileString). A section called '[commands]' can be created
|
||||
with key names defining the virtual command and the value specifying the
|
||||
actual command-line to be used for this virtual command.
|
||||
|
||||
For example, if an INI file has the contents:
|
||||
|
||||
[commands]
|
||||
vpython=c:\bin\vpython.exe -foo
|
||||
|
||||
Then a shebang line of '#! vpython' in a script named 'doit.py' will
|
||||
result in the launcher using the command-line 'c:\bin\vpython.exe -foo
|
||||
doit.py'
|
||||
|
||||
Two .ini files will be searched by the launcher - 'py.ini' in the
|
||||
current user's "application data" directory (ie, the directory returned
|
||||
by calling the Windows function SHGetFolderPath with CSIDL_APPDATA) and
|
||||
'py.ini' in the same directory as the launcher. Commands specified
|
||||
in the "application directory" will have precendence over the one next to
|
||||
the executable, and the same .ini files will be used by both the Windows
|
||||
and Console versions of the launcher.
|
||||
|
||||
Python Version Qualifiers
|
||||
|
||||
Some of the features described allow an optional Python version qualifier
|
||||
to be used.
|
||||
|
||||
A version qualifier starts with a major version number and can optionally
|
||||
be followed by a period ('.') and a minor version specifier. If the minor
|
||||
qualifier is specified, it may optionally be followed by "-32" to indicate
|
||||
the 32bit implementation of that version be used. Note that no "-64"
|
||||
qualifier is necessary as this is the default implementation (see below).
|
||||
|
||||
If no version qualifiers are found, the environment variable PY_PYTHON can
|
||||
be set to specify the default version qualifier - the default value is
|
||||
"2". Note this value could specify just a major version (eg., "2") or a
|
||||
major.minor qualifier (eg., "2.6"), or even major.minor-32.
|
||||
|
||||
If no minor version qualfiers are found, the environment variable
|
||||
PY_PYTHON{major} (where {major} is the current major version qualifier
|
||||
as determined above) can be set to specify the full version. If no such
|
||||
option is found, the launcher will enumerate the installed Python
|
||||
versions and use the latest minor release found for the major version,
|
||||
which is likely, although not guaranteed, to be the most recently
|
||||
installed version in that family.
|
||||
|
||||
On 64bit Windows with both 32bit and 64bit implementations of the
|
||||
same (major.minor) Python version installed, the 64bit version will
|
||||
always be preferred. This will be true for both 32bit and 64bit
|
||||
implementations of the launcher - a 32bit launcher will prefer to
|
||||
execute a 64bit Python installation of the same version if
|
||||
execute a 64bit Python installation of the specified version if
|
||||
available. This is so the behavior of the launcher can be predicted
|
||||
knowing only what versions are installed on the PC and without
|
||||
regard to the order in which they were installed.
|
||||
regard to the order in which they were installed. As noted above, an
|
||||
optional "-32" suffix can be used on a version specifier to change this
|
||||
behaviour.
|
||||
|
||||
Examples:
|
||||
|
||||
* If no relevant options are set, the commands 'python' and
|
||||
'python2' will use the latest Python 2.x version installed and
|
||||
the command 'python3' will use the lastest Python 3.x installed.
|
||||
|
||||
* The commands 'python3.1' and 'python2.7' will not consult any
|
||||
options at all as the versions are fully specified.
|
||||
|
||||
* if 'PY_PYTHON=3', the commands 'python' and 'python3' will both use
|
||||
the latest installed Python 3 version.
|
||||
|
||||
* if 'PY_PYTHON=3.1-32', the command 'python' will use the 32bit
|
||||
implementation of 3.1 whereas the command 'python3' will use the latest
|
||||
installed Python (PY_PYTHON was not considered at all as a major
|
||||
version was specified.)
|
||||
|
||||
* if 'PY_PYTHON=3' and 'PY_PYTHON3=3.1', the commands
|
||||
'python' and 'python3' will both use specifically 3.1
|
||||
|
||||
In addition to environment variables, the same settings can be configured
|
||||
in the .INI file used by the launcher. The section in the INI file will
|
||||
be called '[defaults]' and the key name will be the same as the
|
||||
environment variables without the leading 'PY_' prefix (and note that
|
||||
the key names in the INI file are case insensitive. The contents of
|
||||
an environment variable will override things specified in the INI file.
|
||||
|
||||
For example:
|
||||
* Setting 'PY_PYTHON=3.1' is equivilent to the INI file
|
||||
containing:
|
||||
[defaults]
|
||||
python=3.1
|
||||
|
||||
* Setting 'PY_PYTHON=3' and 'PY_PYTHON3=3.1' is equivilent to the INI file
|
||||
containing:
|
||||
[defaults]
|
||||
python=3
|
||||
python3=3.1
|
||||
|
||||
Command-line handling
|
||||
|
||||
|
@ -238,25 +316,25 @@ Command-line handling
|
|||
|
||||
If the only command-line argument is "-h" or "--help", the launcher will
|
||||
print a small banner and command-line usage, then pass the argument to
|
||||
the default Python. This will have the effect of help for the launcher
|
||||
being printed followed by help for Python itself. The output from the
|
||||
launcher will attempt to clearly indicate the extended help information
|
||||
is coming from the launcher and not Python.
|
||||
the default Python. This will cause help for the launcher being printed
|
||||
followed by help for Python itself. The output from the launcher will
|
||||
attempt to clearly indicate the extended help information is coming from
|
||||
the launcher and not Python.
|
||||
|
||||
As a concession to interactively launching Python, the launcher will
|
||||
support the first command-line argument optionally being a version
|
||||
specifier in the form "-n[.n][:bits]" (where n is a single integer and
|
||||
bits is either '32' or '64') to nominate a specific version be used. For
|
||||
example, while "py.exe" may locate and launch the latest Python 2.x
|
||||
implementation installed, a command-line such as "py.exe -3" could specify
|
||||
the latest Python 3.x implementation be launched, while "py.exe -2.6:32"
|
||||
could specify a 32bit implementation Python 2.6 be located and launched.
|
||||
If a Python 2.x implementation is desired to be launched with the -3 flag,
|
||||
the command-line would need to be similar to "py.exe -2 -3" (or the
|
||||
specific version of Python could obviously be launched manually without
|
||||
use of this launcher.) Note that this feature can not be used with shebang
|
||||
processing as the file scanned for a shebang line and this argument must
|
||||
both be the first argument and therefore are mutually exclusive.
|
||||
support the first command-line argument optionally being a dash ("-")
|
||||
followed by a version qualifier, as described above, to nominate a
|
||||
specific version be used. For example, while "py.exe" may locate and
|
||||
launch the latest Python 2.x implementation installed, a command-line such
|
||||
as "py.exe -3" could specify the latest Python 3.x implementation be
|
||||
launched, while "py.exe -2.6-32" could specify a 32bit implementation
|
||||
Python 2.6 be located and launched. If a Python 2.x implementation is
|
||||
desired to be launched with the -3 flag, the command-line would need to be
|
||||
similar to "py.exe -2 -3" (or the specific version of Python could
|
||||
obviously be launched manually without use of this launcher.) Note that
|
||||
this feature can not be used with shebang processing as the file scanned
|
||||
for a shebang line and this argument must both be the first argument and
|
||||
therefore are mutually exclusive.
|
||||
|
||||
All other arguments will be passed untouched to the child Python process.
|
||||
|
||||
|
@ -275,44 +353,32 @@ Process Launching
|
|||
side effect of this is that the value of sys.executable would refer to the
|
||||
launcher instead of the Python implementation. Many Python scripts use the
|
||||
value of sys.executable to launch child processes, and these scripts may
|
||||
fail to work as expected if the launcher is used - consider a "parent"
|
||||
fail to work as expected if the launcher is used. Consider a "parent"
|
||||
script with a shebang line of '#! /usr/bin/python3' which attempts to
|
||||
launch a child script with no shebang line at all. Currently that
|
||||
child script would be launched using the exact same version running
|
||||
the parent script, but if sys.executable referred to the launcher the
|
||||
child would be likely executed using a Python 2.x version and would be
|
||||
likely to fail with a SyntaxError. A solution for this would need to be
|
||||
found before this could be considered.
|
||||
launch a child script (with no shebang) via sys.executable - currently the
|
||||
child is launched using the exact same version running the parent script.
|
||||
If sys.executable referred to the launcher the child would be likely
|
||||
executed using a Python 2.x version and would be likely to fail with a
|
||||
SyntaxError. A solution for this would need to be found before this could
|
||||
be considered.
|
||||
|
||||
The rules mentioned above regarding 64bit and 32bit programs would also be
|
||||
rendered impossible with this 'in-process' model - a 32bit launcher would
|
||||
be unable to load the 64bit version of Python and vice-versa.
|
||||
Another hurdle is the support for alternative Python implementations
|
||||
using the "customized commands" feature described above, where loading
|
||||
the command dynamically into a running executable is not possible.
|
||||
|
||||
Given the impossibility of supporting the 64bit and 32bit requirements
|
||||
above, the launcher will execute Python in a child process, remaining
|
||||
alive while the child process is executing, then terminate with the same
|
||||
exit code as returned by the child.
|
||||
The final hurdle is the rules above regarding 64bit and 32bit programs -
|
||||
a 32bit launcher would be unable to load the 64bit version of Python and
|
||||
vice-versa.
|
||||
|
||||
To address the concerns regarding the termination of the launcher not
|
||||
killing the child, the Win32 Job API will be used to arrange so that the
|
||||
child process is automatically killed when the parent is terminated
|
||||
(although children of that child process will continue as is the case
|
||||
now.) However, that functionality only works on Windows XP and later, so
|
||||
the launcher running on the Windows 2000 platform will not have this
|
||||
feature - killing the launcher on that platform will keep the child
|
||||
process alive. This feature has been implemented in the reference
|
||||
implementation.
|
||||
|
||||
Alternative implementations and distributions of Python.
|
||||
|
||||
While this PEP is primarily concerned with the python.org distributions of
|
||||
CPython, it does not preclude future enhancements to support both
|
||||
different distributions of CPython (eg. ActivePython, Enthought), nor
|
||||
different implementations of Python (eg. jython, IronPython.)
|
||||
Enhancements to support these alternatives should be proposed by
|
||||
(community or corporate) representatives of these alternatives and
|
||||
addressed via the normal Python development process and after relevant
|
||||
patches have been submitted for the reference implementation.
|
||||
Given these considerations, the launcher will execute it's command in a
|
||||
child process, remaining alive while the child process is executing, then
|
||||
terminate with the same exit code as returned by the child. To address the
|
||||
concerns regarding the termination of the launcher not killing the child,
|
||||
the Win32 Job API will be used to arrange so that the child process is
|
||||
automatically killed when the parent is terminated (although children of
|
||||
that child process will continue as is the case now.) As this Windows API
|
||||
is available in Windows XP and later, this launcher will not work on
|
||||
Windows 2000 or earlier.
|
||||
|
||||
References
|
||||
|
||||
|
@ -320,6 +386,8 @@ References
|
|||
|
||||
[2] http://www.python.org/dev/peps/pep-0394/
|
||||
|
||||
[3] http://bugs.python.org/issue11629
|
||||
|
||||
Copyright
|
||||
|
||||
This document has been placed in the public domain.
|
||||
|
|
Loading…
Reference in New Issue