Use /usr/bin/env python ... why?

Tim Cargile tecargile at hotmail.com
Thu Jan 9 23:12:52 EST 2003


Erik Max Francis <max at alcyone.com> wrote in message news:<3E1E0BE4.1556EDD6 at alcyone.com>...
> Tim Cargile wrote:
> 
> > Use '#!/python' when:
> 
> This cannot be what you really have meant.
>

Yes It was a typo ... or was it a reading comprehension test ...
or was it that I just trying to root for python?  I forget! :-)
No, I haven't resorted to root pythons ... yet! 
 
> > Use '#!env python' when:
> 
> It's unlikely that this was either.

Actually this worked with Cygin ... which is known to be a
little strange.  BUT ONLY when the *.py module was launched
through a shell wrapper that did an 'eval exec *.py'.

See my rather redundant response to Steve Holden re this.

I still failed my usually thorough Q/A phase in a 'rush
to shipit'.  :-)

> 
> > Oh well, at least I have not seen these:
> > 
> >  #!env /usr/bin/python
> > 
> >    and
> > 
> > #!/usr/bin/env /usr/bin/python
> > 
> > These works also, but have yet to observe them in the wild.
> 
> Because they defeat the purpose of using env in the first place.
>

Exactly. Unless there was a 'name=value' arugment to 'env'.
In that case they are the more efficient - BUT potentially problematic
portability-wise.
 
> A few points here:
> 
> You're not guaranteed that env will be in /usr/bin, although admittedly
> it's pretty rare that it is not.

Agreed.  That's how all these scripts can get away with using the
fullpath.  Fullpath is not bad for referencing intrinsic Unix
utilities.
If they moved a lot of shell scripts would break.

> 
> /usr/bin/env python searches the PATH for the first executable named
> `python' and sets up the environment appropriately.  This has the
> benefit of having a good chance of finding a Python interpreter, but has
> the downside that you don't have much choice in which one is chosen (if
> there are multiple installed on the same system).  Furthermore, which
> one it finds is dependent on the PATH, and the PATH can vary quite a bit
> between interactive shells, CGI scripts, and cron jobs.  For instance,
> if you are in the (not uncommon) situation where a legacy interpreter is
> in /usr/bin (possibly one that the installation requires, like in the
> case of Red Hat) and a newer one is /usr/local/bin, you're almost
> certain to find that scripts requiring the more recent interpreter will
> work in interactive shells but won't work in cron jobs or CGI scripts
> (because env will find the legacy interpreter, not the new one).

See my response to Steve Holden and the CM issues involved with
setting
the she-bang line globally and automatically through mass source
editing or a make/build operation.

> 
> A slightly better way is searching for the version you want, e.g.
> /usr/bin/env python2.2, but that presents its own share of problems,
> namely limiting yourself in precisely which interpreter gets found (that
> is, env exists to find it for you, and you're now limiting it).

One approach is to designate a specific fullpath that is guaranteed
(if one has the control) and is the preferred one.  New releases would
have be in a different location for testing and then moved to the
designated fullpath afterwards.  For testing this would mean that
a copied set of all the *.py modules would have to mass-edited
to replace the designated fullpath with the new-release fullpath.
This is fairly easy to do manually with simple tools like 'shar'
and vi if one didn't want to write a script to do it.  The
'#!/usr/bin/env python' (or '#!/usr/bin/python, for that matter)
line is rather unique and could be easily globally edited.
This means a second, complete copy of the source needs to be in
existence
for a period of time. 

> 
> A hard-coded path such as /usr/bin/python or /usr/local/bin/python is
> restrictive but will be guaranteed to get what you want, should what you
> want be in those locations.

And also guaranteed that there are no 'trojans' can sneak in and
variations in $PATH don't nail you as well as the performance gain
from a fullpath execution ...

Need I say more?

> 
> As I said in another thread, there's really no "magic bullet," since
> PATHs can vary from invocation to invocation.  I personally tend to
> prefer /usr/local/bin/... in the bangpath simply because I default to
> assuming that one has control over what's in /usr/local/bin and thus can
> rely on that being more likely to be the version that is desired.

I can go with that.  Whatever 'designated' directory makes sense.
Cygwin plunked 2.2 down in /usr/bin.
 
> Obviously, that can't always be true, but one can always manually change
> the bangpath.  I find that the often surprising unpredictability of
> using env on systems with multiple Python interpreters far outweighs the
> helpfulness of having things "work out of the box."

Agreed.  It got this far with 'env', but maybe it's time for paradigm
shift?

Thanks very much.  Great response!  We're preaching to each other's
choir.




More information about the Python-list mailing list