I'm in a bit of an interesting situation where I have a Python script that can theoretically be run by a variety of users with a variety of environments (and PATHs) and on a variety of Linux systems. I want this script to be executable on as many of these as possible without artificial restrictions. Here are some known setups:
- Python 2.6 is the system Python version, so python, python2, and python2.6 all exist in /usr/bin (and are equivalent).
- Python 2.6 is the system Python version, as above, but Python 2.7 is installed alongside it as python2.7.
- Python 2.4 is the system Python version, which my script does not support. In /usr/bin we have python, python2, and python2.4 which are equivalent, and python2.5, which the script supports.
I want to run the same executable python script on all three of these. It would be nice if it tried to use /usr/bin/python2.7 first, if it exists, then fall back to /usr/bin/python2.6, then fall back to /usr/bin/python2.5, then simply error out if none of those were present. I'm not too hung up on it using the most recent 2.x possible, though, as long as it's able to find one of the correct interpreters if present.
My first inclination was to change the shebang line from:
#!/usr/bin/python
to
#!/usr/bin/python2.[5-7]
since this works fine in bash. But running the script gives:
/usr/bin/python2.[5-7]: bad interpreter: No such file or directory
Okay, so I try the following, which also works in bash:
#!/bin/bash -c /usr/bin/python2.[5-7]
But again, this fails with:
/bin/bash: - : invalid option
Okay, obviously I could just write a separate shell script that finds the correct interpreter and runs the python script using whatever interpreter it found. I'd just find it a hassle to distribute two files where one should suffice as long as it's run with the most up-to-date python 2 interpreter installed. Asking people to invoke the interpreter explicitly (e.g., $ python2.5 script.py
) is not an option. Relying on the user's PATH being set up a certain way is also not an option.
Edit:
Version checking within the Python script is not going to work since I'm using the "with" statement which exists as of Python 2.6 (and can be used in 2.5 with from __future__ import with_statement
). This causes the script to fail immediately with a user-unfriendly SyntaxError, and prevents me from ever having an opportunity to check the version first and emit an appropriate error.
Example: (try this with a Python interpreter less than 2.6)
#!/usr/bin/env python
import sys
print "You'll never see this!"
sys.exit()
with open('/dev/null', 'w') as out:
out.write('something')
Best Answer
I'm not expert, but I believe that you shouldn't specify exact python version to use and leave that choice to system/user.
Also you should use that instead of hardcoding path to python in script:
or
It is recommended by Python doc in all versions:
In various distributions Python may be installed in different places, so
env
will search for it inPATH
. It should be available in all major Linux distributions and from what I see in FreeBSD.Script should be executed with that version of Python which is in your PATH and which is chosen by your distribution*.
If your script is compatible with all version of Python except 2.4 you should just check inside of it if it is run in Python 2.4 and print some info and exit.
More to read
env
.Footnote
*In Gentoo there is tool called
eselect
. Using it you may set default versions of different applications (including Python) as default: