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:
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.
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')