Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a Python script that need to be run with a particular python installation. Is there a way to craft a shebang so that it runs with $FOO/bar/MyCustomPython?

share|improve this question
up vote 17 down vote accepted

The shebang line is very limited. Under many unix variants (including Linux), you can have only two words: a command and a single argument. There is also often a length limitation.

The general solution is to write a small shell wrapper. Name the Python script foo.py, and put the shell script next to foo.py and call it foo. This approach doesn't require any particular header on the Python script.

exec "$FOO/bar/MyCustomPython" "$0.py" "$@"

Another tempting approach is to write a wrapper script like the one above, and put #!/path/to/wrapper/script as the shebang line on the Python script. However, most unices don't support chaining of shebang scripts, so this won't work.

If MyCustomPython was in the $PATH, you could use env to look it up:

#!/usr/bin/env MyCustomPython
import …

Yet another approach is to arrange for the script to be both a valid shell script (which loads the right Python interpreter on itself) and a valid script in the target language (here Python). This requires that you find a way to write such a dual-language script for your target language. In Perl, this is known as if $running_under_some_shell.

eval 'exec "$FOO/bar/MyCustomPerl" -wS $0 ${1+"$@"}'
    if $running_under_some_shell;
use …

Here's one way to achieve the same effect in Python. In the shell, "true" is the true utility, which ignores its arguments (two single-character strings : and ') and returns a true value. In Python, "true" is a string which is true when interpreted as a boolean, so this is an if instruction that's always true and executes a string literal.

if "true" : '''\'
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
import …

Rosetta code has such dual-language scripts in several other languages.

share|improve this answer
@Chris: everything is inside single quotes. Please explain… – Stéphane Gimenez Sep 17 '11 at 1:17
Thanks. I was looking for a single file solution. – eric.frederich Sep 19 '11 at 13:08
You are a bloody wizard... This is great. I used this to edit the PYTHONPATH env variable to load modules from a non-standard location for a CGI script on a system I didn't have root access to. Life saver. Thanks again. – wspurgin Feb 16 at 21:00

Shebang lines do not undergo variable expansion, so you cannot use $FOO/MyCustomPython as it would search for an executable named dollar-F-O-O-...

An alternative is to have your shebang point to a shell script as the interpreter, and this shell script can then use environment variables to locate the correct one and exec it.

Example: create a mypython.sh script in /usr/local/bin (or any other directory on your $PATH), with the following content:

#! /bin/sh
exec "$PYTHON" "$@"

then you can use this shebang line to have a Python script executed through MyCustomPython via mypython.sh:

#!/usr/bin/env mypython.sh
share|improve this answer
Use $python, not $PYTHON -- by convention, we capitalize environment variables (PAGER, EDITOR, SHELL ... $PYTHON in your script is not an environment variable) and internal shell variables (BASH_VERSION, RANDOM, ...). All other variable names should contain at least one lowercase letter. This convention avoids accidentally overriding environmental and internal variables. Also, don't use extensions for your scripts. Scripts define new commands that you can run, and commands are generally not given extensions. – Chris Down Sep 16 '11 at 18:20

You can either use the absolute path to the custom python installation, or you can put it in your $PATH and use #!/usr/bin/env [command]. Otherwise, write a wrapper for it and use exec to replace the process image, as an example:

exec "$ENV/python" "$@"
share|improve this answer

First, determine how your version of Python is different from the standard Python already installed (for example, an additional module) and then at the start of the program 'switch' how the Python is called:

import os
import sys
    import MyCustomModule
except ImportError:
    # only need to use expandvar if you know the string below has an envvar
    custprog = os.path.expandvar("$FOO/bar/MyCustomPython")
    os.execv(custprog, sys.argv) # call alternate python with the same arguments
    raise SystemExit('could not call %s' % custprog)
# if we get here, then we have the correct python interpreter

This should allow the program to be called by any other instance of Python. I do something similar for an instance with built-in sql library that cannot be imported as a module in the system's python.

share|improve this answer

If you can replace $FOO in $FOO/bar/MyCustomPython with concrete path options, you can tell the env shebang line where to look up your custom Python version by directly setting a custom PATH in it.

#!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python

Edit: Seems to work only without quotes around the PATH value assignment:

#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python
share|improve this answer
Beware that this doesn't work on all unix variants (e.g. not on Linux). And you're removing all the existing directories from the path, which is likely to cause problems down the line. – Gilles Sep 17 '11 at 20:52
Better expand PATH like this: PATH=$PATH:/path/to/whatever... – Bengt Jun 26 '14 at 12:17

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.