Wiki

Clone wiki

simple_launcher / Launching an interpreter in a location relative to the launcher executable

There are applications which require the Python interpreter for the launcher executable to be found in a location relative to the launcher executable itself. The launcher finds the interpreter using a shebang line. Currently, the interpreter-specifying part of the shebang can take one of several forms:

  1. An absolute path for the interpreter is specified, with or without quoting to support spaces in the file name.
  2. A relative path for the interpreter is specified, with or without quoting to support spaces in the file name. Windows interprets this path as relative to the current directory.
  3. The special form /usr/bin/env <name> is used, in which case the launcher looks for the interpreter on the PATH using <name>.

A proposal to support finding the interpreter in a location relative to the launcher executable itself is as follows:

  1. Look for a shebang beginning with the special prefix text <launcher_dir>\. As < and > are not legal characters in Windows paths, this formulation is not expected to exist in the wild, for working scripts. If this prefix (searched for case-insensitively) is not found, the special processing below is not invoked.
  2. If the special prefix is found, it is expected to be followed by a relative path which is to be interpreted as relative to the launcher executable's own directory. The interpreter path will be constructed using the launcher executable's directory, combined with the relative path following the prefix.
  3. If the relative path begins with a double quote, it must end with a double quote, and these quotes will be removed before combining with the launcher executable's directory. If the resulting path contains a space, the resulting interpreter path will be quoted with a double quote; otherwise it will be unquoted.

The interpreter identified through the above process will be used to generate the command line used to run the script.

Example relevant shebang portions with resulting interpreter paths, where the launcher executable is found at c:\path\to\launcher.exe:

  • python.exe -> python.exe
  • foo.exe -> foo.exe
  • /usr/bin/env foo -> location of foo as found on the PATH using PATHEXT to determine extension
  • subdir\foo.exe -> subdir\foo.exe, assume Windows will find the interpreter in subdir\foo.exe relative to the current directory.
  • <launcher_dir>\foo.exe -> c:\path\to\foo.exe
  • <launcher_dir>\..\foo.exe -> c:\path\foo.exe
  • <launcher_dir>\"..\foo.exe" -> c:\path\foo.exe
  • <launcher_dir>\"..\sibling path\foo.exe" -> "c:\path\sibling path\foo.exe"
  • <launcher_dir>\"..\..\fun stuff\foo.exe" -> "c:\fun stuff\foo.exe"
  • <launcher_dir>\..\sibling path\foo.exe -> "c:\path\sibling path\foo.exe"
  • <launcher_dir>\..\..\fun stuff\foo.exe -> "c:\fun stuff\foo.exe"

If the launcher is found in a directory with spaces, such as c:\path with spaces\to\launcher.exe, then the resulting interpreter path where the shebang starts with <launcher_dir>\ will always be quoted.

Update 1: In the first two cases above, and the fourth case, the value is passed to Windows as-is, with no further processing. Windows will do whatever it does to find the executable. This is different from the third case, where the launcher explicitly tries to find the named executable on the PATH using PATHEXT. It's mainly there to allow cross-platform compatibility for /usr/bin/env python[X[.Y]], which otherwise wouldn't work on Windows. Of course, it should also work with /usr/bin/env foo.

Updated