avoiding long paths to interpreter

Tim Cargile tecargile at hotmail.com
Wed Jan 15 15:02:10 EST 2003


Mathew Yeates <mathew at fugue.jpl.nasa.gov> wrote in message news:<aviaqo$9k6$1 at nntp1.jpl.nasa.gov>...
> in TCL, there is a trick where, instead of
> writing
> #![long path to tcl interpreter]
> 
> you write
> #!/bin/sh
> .
> . some magic, I don't remember what
> .
> 
> Is there an equivalent in python? What is the
> bast way to distibute a python script without
> knowing the users path to the python executable?
> 
> Mathew


There is a FAQ 4.63 from python.org regarding this but,
as Erik Max Francis has pointed out in this thread, there may be
limitations w/r '/usr/bin/env' that may eliminate using it and require
use of the following (as the first three lines of a python module
that is desired to be run):


  #! /bin/sh
  """:"
  exec python $0 ${1+"$@"}
  """

Note: Bourne shell syntax should be used for all shell statements for 
portability because '/bin/sh' may actually be 'Korn' or 'BASH'
on some platforms.

I'm not a big proponent of mixing the shell and python languages and
having interpreter A read interpreter B's file and recognize statements
that are buried in interpreter B's documentation sections ... but if
one is forced to this ... one can at least do it with some style.  :-)

So, I've come up with some additional reasons/extensions to the above 'hack'
- which is actually at the beginning of the python module that is desired
to be run and performs an interpreter swap-out (exec) after initially
identifying the module as a shell executable (#!/bin/sh).

The shell variables following 'python' are the module file
name ($0) and arguments passed to the module (${1+"$@"}).
Perhaps these approaches could further assist in limitations placed
on CGI scripts due to a limited path that is mentioned in FAQ 4.63.


Some Extensions (that have actually been tested):


1) If the PATH needed to be adjusted to have the desired python path
   prepended (PATH=python_path:${PATH}):

  #! /bin/sh
  """:"
  PATH=/usr/local/bin:${PATH}
  exec python $0 ${1+"$@"}
  """

2) If the 'python' needed to be selected preferentially,
   without altering or searching the PATH, for example:

  #! /bin/sh
  """:"
  if [ -x /usr/local/bin/python ];then
      exec /usr/local/bin/python $0 ${1+"$@"}
  elif [ -x /usr/bin/python ];then
      exec /usr/bin/python $0 ${1+"$@"}
  else
      echo "$0: Cannot find python in /usr/local/bin, /usr/bin" >&2
      exit 2
  fi
  """

3) Having a known-to-exist absolute path used in the 'exec' statement
   (/usr/local/bin in this example) to avoid a path search:

  #! /bin/sh
  """:"
  #--- 
  #--- Place your desired pre-exec shell statements here.
  #--- 
  exec /usr/local/bin/python $0 ${1+"$@"}
  """

Of course, with 3), it could have been or should have been done on line 1,
thusly:

#!/usr/local/bin/python

So ... there should be some additional shell statments preceding
the 'exec' to justify using it one would think.

If all this looks too much like hard-coding shell statements into a
python module, you're correct.  And it could be a maintenance hassle.
One way to avoid this is to have the shell component 'dot' execute a
file containing the statements.  This is like a very simplistic
python 'import' in general purpose.  All it does is find the file
and switch shell interpretation input it, then back to the original file
at the EOF of the 'dot' file.  It will allow a single file to support
multiple python modules so that changes to its behavior can be
made in one file and they affect all python modules.  Also, ideally,
changes to the python modules would not be required in the future.

Using a 'dot' file only lines (and the 'shell dot' file, of course)
are required by the python module in order to perform the 'exec':

  #! /bin/sh
  """:"
  . exec_python
  """

Contents of 'exec_python' 'shell dot' file (based on example 1, above):

  PATH=/usr/local/bin:${PATH}
  exec python $0 ${1+"$@"}


It requires the 'exec_python' file to be on the PATH to be found,
but it can probably reside in the same directory as the python
module(s) that references it, since the referencing script(s) must
have been found also using PATH.  The 'exec_python' ('shell dot')
module does not have to be executable, since it is only read and
not really executed.


Hope this helps,




More information about the Python-list mailing list