0

(Asking a question in order to answer it, having been initially puzzled by this. Other answers obviously welcome.)

Using #!/usr/bin/env python is a common trick to allow the python interpreter to be found using a PATH lookup, rather than hard-coding the path to python. It could be convenient to be adapt this to add a PATH=... argument to env, in order to hard-code a list of candidate directories while not hard-coding a single exact path. (This would make use of the fact that env uses the specified PATH variable when locating python, aside from passing it to the python process.)

For example (in test.py):

#!/usr/bin/env PATH=/opt/python/bin:/usr/bin:/bin python

import sys
print(sys.executable)  # show which executable it found

But if you try this, although the command works if executed explicitly from the shell command line:

$ echo $PATH
/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

$ /usr/bin/env PATH=/opt/python/bin:/usr/bin:/bin python ./test.py
/opt/python/bin/python

it fails when trying to run it via the shebang:

$ ./test.py
[hangs - infinite loop]

Why is this, and what can be done instead?

alani
  • 12,573
  • 2
  • 13
  • 23

1 Answers1

0

Regarding why it fails, it turns out that this is an example of the problem described here.

As regards what can be done about it, it is possible to adapt various this workaround to a similar problem, namely how to pass an argument to python in #!/usr/bin/env python (which although it is not exactly the same problem, also relates to wanting to have more than two items in the shebang line).

This gives:

#!/bin/sh
''''export PATH=/opt/python/bin:/usr/bin:/bin; exec python "$0" # '''

import sys
print(sys.executable)

Invoking it via the shebang, we get:

$ ./test.py 
/opt/python/bin/python

Solutions involving #!/usr/bin/env -S PATH=... python (GNU coreutils >= 8.30) still appear not to be sufficiently portable (e.g. Ubuntu 18.04.4, which was the latest LTS release until April 2020, has coreutils 8.28).

alani
  • 12,573
  • 2
  • 13
  • 23