Python deployment and /usr/bin/env portability - python

At the beginning of all my executable Python scripts I put the shebang line:
#!/usr/bin/env python
I'm running these scripts on a system where env python yields a Python 2.2 environment. My scripts quickly fail because I have a manual check for a compatible Python version:
if sys.version_info < (2, 4):
raise ImportError("Cannot run with Python version < 2.4")
I don't want to have to change the shebang line on every executable file, if it's possible; however, I don't have administrative access to the machine to change the result of env python and I don't want to force a particular version, as in:
#!/usr/bin/env python2.4
I'd like to avoid this because system may have a newer version than Python 2.4, or may have Python 2.5 but no Python 2.4.
What's the elegant solution?
[Edit:] I wasn't specific enough in posing the question -- I'd like to let users execute the scripts without manual configuration (e.g. path alteration or symlinking in ~/bin and ensuring your PATH has ~/bin before the Python 2.2 path). Maybe some distribution utility is required to prevent the manual tweaks?

"env" simply executes the first thing it finds in the PATH env var. To switch to different python, prepend the directory for that python's executable to the path before invoking your script.

Pretty hackish solution - if your check fails, use this function (which probably could be significantly improved) to determine the best interpreter available, determine if it is acceptable, and if so relaunch your script with os.system or something similar and your sys.argv using the new interpreter.
import os
import glob
def best_python():
plist = []
for i in os.getenv("PATH").split(":"):
for j in glob.glob(os.path.join(i, "python2.[0-9]")):
plist.append(os.path.join(i, j))
plist.sort()
plist.reverse()
if len(plist) == 0: return None
return plist[0]

If you are running the scripts then you can set your PATH variable to point to a private bin directory first:
$ mkdir ~/bin
$ ln -s `which python2.4` ~/bin/python
$ export PATH=~/bin:$PATH
Then when you execute your python script it'll use python 2.4. You'll have to change your login scripts to change your PATH.
Alternatively run your python script with the explicit interpreter you want:
$ /path/to/python2.4 <your script>

#morais: That's an interesting idea, but I think maybe we can take it one step farther. Maybe there's a way to use Ian Bicking's virtualenv to:
See if we're running in an acceptable environment to begin with, and if so, do nothing.
Check if there exists a version-specific executable on the PATH, i.e. check if python2.x exists for x in reverse(range(4, 10)). If so, re-run the command with the better interpreter.
If no better interpreter exists, use virtualenv to try and install a newer version of Python from the older version of Python and get any prerequisite packages.
I have no idea if virtualenv is capable of this, so I'll go mess around with it sometime soon. :)

Here's a solution if you're (1) absolutely set on using shebangs and (2) able to use Autotools in your build process.
I just found last night that you can use the autoconf macro AM_PATH_PYTHON to find a minimal Python 2 binary. The how-to is here.
So, your process would be:
Issue an AM_PATH_PYTHON(2.4) in your configure.ac
Rename all of your .py scripts to .py.in (in my experience, this doesn't confuse vi)
Name all of those Python scripts you want to generate with AC_CONFIG_FILES.
Instead of starting with #!/usr/bin/env python, use #!#PYTHON#
Then your resultant Python scripts will always have an appropriate shebang.
So, you have this solution, at least possible, if not practical.

Related

Monterey. zsh: ./flashimage.py: bad interpreter: /usr/bin/python: no such file or directory [duplicate]

Should I put the shebang in my Python scripts? In what form?
#!/usr/bin/env python
or
#!/usr/local/bin/python
Are these equally portable? Which form is used most?
Note: the tornado project uses the shebang. On the other hand the Django project doesn't.
The shebang line in any script determines the script's ability to be executed like a standalone executable without typing python beforehand in the terminal or when double clicking it in a file manager (when configured properly). It isn't necessary but generally put there so when someone sees the file opened in an editor, they immediately know what they're looking at. However, which shebang line you use is important.
Correct usage for (defaults to version 3.latest) Python 3 scripts is:
#!/usr/bin/env python3
Correct usage for (defaults to version 2.latest) Python 2 scripts is:
#!/usr/bin/env python2
The following should not be used (except for the rare case that you are writing code which is compatible with both Python 2.x and 3.x):
#!/usr/bin/env python
The reason for these recommendations, given in PEP 394, is that python can refer either to python2 or python3 on different systems.
Also, do not use:
#!/usr/local/bin/python
"python may be installed at /usr/bin/python or /bin/python in those
cases, the above #! will fail."
―"#!/usr/bin/env python" vs "#!/usr/local/bin/python"
It's really just a matter of taste. Adding the shebang means people can invoke the script directly if they want (assuming it's marked as executable); omitting it just means python has to be invoked manually.
The end result of running the program isn't affected either way; it's just options of the means.
Should I put the shebang in my Python scripts?
Put a shebang into a Python script to indicate:
this module can be run as a script
whether it can be run only on python2, python3 or is it Python 2/3 compatible
on POSIX, it is necessary if you want to run the script directly without invoking python executable explicitly
Are these equally portable? Which form is used most?
If you write a shebang manually then always use #!/usr/bin/env python unless you have a specific reason not to use it. This form is understood even on Windows (Python launcher).
Note: installed scripts should use a specific python executable e.g., /usr/bin/python or /home/me/.virtualenvs/project/bin/python. It is bad if some tool breaks if you activate a virtualenv in your shell. Luckily, the correct shebang is created automatically in most cases by setuptools or your distribution package tools (on Windows, setuptools can generate wrapper .exe scripts automatically).
In other words, if the script is in a source checkout then you will probably see #!/usr/bin/env python. If it is installed then the shebang is a path to a specific python executable such as #!/usr/local/bin/python (NOTE: you should not write the paths from the latter category manually).
To choose whether you should use python, python2, or python3 in the shebang, see PEP 394 - The "python" Command on Unix-Like Systems:
... python should be used in the shebang line only for scripts that are
source compatible with both Python 2 and 3.
in preparation for an eventual change in the default version of
Python, Python 2 only scripts should either be updated to be source
compatible with Python 3 or else to use python2 in the shebang line.
If you have more than one version of Python and the script needs to run under a specific version, the she-bang can ensure the right one is used when the script is executed directly, for example:
#!/usr/bin/python2.7
Note the script could still be run via a complete Python command line, or via import, in which case the she-bang is ignored. But for scripts run directly, this is a decent reason to use the she-bang.
#!/usr/bin/env python is generally the better approach, but this helps with special cases.
Usually it would be better to establish a Python virtual environment, in which case the generic #!/usr/bin/env python would identify the correct instance of Python for the virtualenv.
The purpose of shebang is for the script to recognize the interpreter type when you want to execute the script from the shell.
Mostly, and not always, you execute scripts by supplying the interpreter externally.
Example usage: python-x.x script.py
This will work even if you don't have a shebang declarator.
Why first one is more "portable" is because, /usr/bin/env contains your PATH declaration which accounts for all the destinations where your system executables reside.
NOTE: Tornado doesn't strictly use shebangs, and Django strictly doesn't. It varies with how you are executing your application's main function.
ALSO: It doesn't vary with Python.
You should add a shebang if the script is intended to be executable. You should also install the script with an installing software that modifies the shebang to something correct so it will work on the target platform. Examples of this is distutils and Distribute.
Sometimes, if the answer is not very clear (I mean you cannot decide if yes or no), then it does not matter too much, and you can ignore the problem until the answer is clear.
The #! only purpose is for launching the script. Django loads the sources on its own and uses them. It never needs to decide what interpreter should be used. This way, the #! actually makes no sense here.
Generally, if it is a module and cannot be used as a script, there is no need for using the #!. On the other hand, a module source often contains if __name__ == '__main__': ... with at least some trivial testing of the functionality. Then the #! makes sense again.
One good reason for using #! is when you use both Python 2 and Python 3 scripts -- they must be interpreted by different versions of Python. This way, you have to remember what python must be used when launching the script manually (without the #! inside). If you have a mixture of such scripts, it is a good idea to use the #! inside, make them executable, and launch them as executables (chmod ...).
When using MS-Windows, the #! had no sense -- until recently. Python 3.3 introduces a Windows Python Launcher (py.exe and pyw.exe) that reads the #! line, detects the installed versions of Python, and uses the correct or explicitly wanted version of Python. As the extension can be associated with a program, you can get similar behaviour in Windows as with execute flag in Unix-based systems.
When I installed Python 3.6.1 on Windows 7 recently, it also installed the Python Launcher for Windows, which is supposed to handle the shebang line. However, I found that the Python Launcher did not do this: the shebang line was ignored and Python 2.7.13 was always used (unless I executed the script using py -3).
To fix this, I had to edit the Windows registry key HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. This still had the value
"C:\Python27\python.exe" "%1" %*
from my earlier Python 2.7 installation. I modified this registry key value to
"C:\Windows\py.exe" "%1" %*
and the Python Launcher shebang line processing worked as described above.
Answer: Only if you plan to make it a command-line executable script.
Here is the procedure:
Start off by verifying the proper shebang string to use:
which python
Take the output from that and add it (with the shebang #!) in the first line.
On my system it responds like so:
$which python
/usr/bin/python
So your shebang will look like:
#!/usr/bin/python
After saving, it will still run as before since python will see that first line as a comment.
python filename.py
To make it a command, copy it to drop the .py extension.
cp filename.py filename
Tell the file system that this will be executable:
chmod +x filename
To test it, use:
./filename
Best practice is to move it somewhere in your $PATH so all you need to type is the filename itself.
sudo cp filename /usr/sbin
That way it will work everywhere (without the ./ before the filename)
If you have different modules installed and need to use a specific
python install, then shebang appears to be limited at first. However,
you can do tricks like the below to allow the shebang to be invoked
first as a shell script and then choose python. This is very flexible
imo:
#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; then
echo Using preferred python $PREFERRED_PYTHON
exec $PREFERRED_PYTHON "$0" "$#"
elif [ -x $ALTERNATIVE_PYTHON ]; then
echo Using alternative python $ALTERNATIVE_PYTHON
exec $ALTERNATIVE_PYTHON "$0" "$#"
else
echo Using fallback python $FALLBACK_PYTHON
exec python3 "$0" "$#"
fi
exit 127
'''
__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())
Or better yet, perhaps, to facilitate code reuse across multiple python scripts:
#!/bin/bash
"true" '''\'; source $(cd $(dirname ${BASH_SOURCE[#]}) &>/dev/null && pwd)/select.sh; exec $CHOSEN_PYTHON "$0" "$#"; exit 127; '''
and then select.sh has:
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; then
CHOSEN_PYTHON=$PREFERRED_PYTHON
elif [ -x $ALTERNATIVE_PYTHON ]; then
CHOSEN_PYTHON=$ALTERNATIVE_PYTHON
else
CHOSEN_PYTHON=$FALLBACK_PYTHON
fi
This is really a question about whether the path to the Python interpreter should be absolute or logical (/usr/bin/env) with respect to portability.
My view after thoroughly testing the behavior is that the logical path in the she-bang is the better of the two options.
Being a Linux Engineer, my goal is always to provide the most suitable, optimized hosts for my developer clients, so the issue of Python environments is something I really need a solid answer to. Encountering other answers on this and other Stack Overflow sites which talked about the issue in a general way without supporting proofs, I've performed some really granular testing & analysis on this very question on Unix.SE.
For files that are intended to be executable from the command-line, I would recommend
#! /usr/bin/env python3
Otherwise you don't need the shebang (though of course it doesn't harm).
If you use virtual environments like with pyenv it is better to write #!/usr/bin/env python
The pyenv setting will control which version of python and from which file location is started to run your script.
If your code is known to be version specific, it will help others to find why your script does not behave in their environment if you specify the expected version in the shebang.
If you want to make your file executable you must add shebang line to your scripts.
#!/usr/bin/env python3
is better option in the sense that this will not be dependent on specific distro of linux but could be used on almost all linux distro since it hunts for the python3 path from environment variables, which is different for different distros of linux.
whereas
#!/usr/local/bin/python3
would be a distro specific path for python3 and would not work if python3 is not found on this path, and could result in confusion and ambiguity for developer when migrating from one distro to another of linux.
Use first
which python
This will give the output as the location where my python interpreter (binary) is present.
This output could be any such as
/usr/bin/python
or
/bin/python
Now appropriately select the shebang line and use it.
To generalize we can use:
#!/usr/bin/env
or
#!/bin/env

How do i know if a script is to be run with Python 2 or Python 3 [duplicate]

How do I, in the main.py module (presumably), tell Python which interpreter to use? What I mean is: if I want a particular script to use version 3 of Python to interpret the entire program, how do I do that?
Bonus: How would this affect a virtualenv? Am I right in thinking that if I create a virtualenv for my program and then tell it to use a different version of Python, then I may encounter some conflicts?
You can add a shebang line the to the top of the script:
#!/usr/bin/env python2.7
But that will only work when executing as ./my_program.py.
If you execute as python my_program.py, then the whatever Python version that which python returns will be used.
In re: to virtualenv use: virtualenv -p /usr/bin/python3.2 or whatever to set it up to use that Python executable.
Perhaps not exactly what you asked, but I find this to be useful to put at the start of my programs:
import sys
if sys.version_info[0] < 3:
raise Exception("Python 3 or a more recent version is required.")
I would use the shebang #!/usr/bin/python (first line of code) with the serial number of Python at the end
Then run the Python file as a script, e.g., ./main.py from the command line, rather than python main.py.
It is the same when you want to run Python from a Linux command line.
While the OP may be working on a nix platform this answer could help non-nix platforms. I have not experienced the shebang approach work in Microsoft Windows.
Rephrased: The shebang line answers your question of "within my script" but I believe only for Unix-like platforms. Even though it is the Unix shell, outside the script, that actually interprets the shebang line to determine which version of Python interpreter to call. I am not sure, but I believe that solution does not solve the problem for Microsoft Windows platform users.
In the Microsoft Windows world, the simplify the way to run a specific Python version, without environment variables setup specifically for each specific version of Python installed, is just by prefixing the python.exe with the path you want to run it from, such as C:\Python25\python.exe mymodule.py or D:\Python27\python.exe mymodule.py
However you would need to consider the PYTHONPATH and other PYTHON... environment variables that would point to the wrong version of Python libraries.
For example, you might run:
C:\Python2.5.2\python.exe mymodule
Yet, the environment variables may point to the wrong version as such:
PYTHONPATH = D:\Python27
PYTHONLIB = D:\Python27\lib
Loads of horrible fun!
So a non-virtualenv way, in Windows, would be to use a batch file that sets up the environment and calls a specific Python executable via prefixing the python.exe with the path it resides in. This way has additional details you'll have to manage though; such as using command line arguments for either of the "start" or "cmd.exe" command to "save and replace the "console" environment" if you want the console to stick around after the application exits.
Your question leads me to believe you have several Python modules, each expecting a certain version of Python. This might be solvable "within" the script by having a launching module which uses the subprocess module. Instead of calling mymodule.py you would call a module that calls your module; perhaps launch_mymodule.py
launch_mymodule.py
import sys
import subprocess
if sys.argv[2] == '272':
env272 = {
'PYTHONPATH': 'blabla',
'PYTHONLIB': 'blabla', }
launch272 = subprocess.Popen('D:\\Python272\\python.exe mymodule.py', env=env272)
if sys.argv[1] == '252'
env252 = {
'PYTHONPATH': 'blabla',
'PYTHONLIB': 'blabla', }
launch252 = subprocess.Popen('C:\\Python252\\python.exe mymodule.py', env=env252)
I have not tested this.
You can't do this within the Python program, because the shell decides which version to use if you a shebang line.
If you aren't using a shell with a shebang line and just type python myprogram.py it uses the default version unless you decide specifically which Python version when you type pythonXXX myprogram.py which version to use.
Once your Python program is running you have already decided which Python executable to use to get the program running.
virtualenv is for segregating python versions and environments, it specifically exists to eliminate conflicts.
For those using pyenv to control their virtual environments, I have found this to work in a script:
#!/home/<user>/.pyenv/versions/<virt_name>/bin/python
DO_STUFF
I had this problem and just decided to rename one of the programs from python.exe to python2.7.exe. Now I can specify on command prompt which program to run easily without introducing any scripts or changing environmental paths.
So i have two programs: python2.7 and python (the latter which is v.3.8 aka default).
While working with different versions of Python on Windows,
I am using this method to switch between versions.
I think it is better than messing with shebangs and virtualenvs
install python versions you desire
go to Environment Variables > PATH
(I assume that paths of python versions are already added to Env.Vars.>PATH)
suppress the paths of all python versions you dont want to use
(don't delete the paths, just add a suffix like "_sup")
call python from terminal
(so Windows will skip the wrong paths you changed,
and will find the python.exe at the path you did not suppressed,
and will use this version after on)
switch between versions by playing with suffixes

Attempting to make python file executable on mac. Bad interpreter, permission denied [duplicate]

Should I put the shebang in my Python scripts? In what form?
#!/usr/bin/env python
or
#!/usr/local/bin/python
Are these equally portable? Which form is used most?
Note: the tornado project uses the shebang. On the other hand the Django project doesn't.
The shebang line in any script determines the script's ability to be executed like a standalone executable without typing python beforehand in the terminal or when double clicking it in a file manager (when configured properly). It isn't necessary but generally put there so when someone sees the file opened in an editor, they immediately know what they're looking at. However, which shebang line you use is important.
Correct usage for (defaults to version 3.latest) Python 3 scripts is:
#!/usr/bin/env python3
Correct usage for (defaults to version 2.latest) Python 2 scripts is:
#!/usr/bin/env python2
The following should not be used (except for the rare case that you are writing code which is compatible with both Python 2.x and 3.x):
#!/usr/bin/env python
The reason for these recommendations, given in PEP 394, is that python can refer either to python2 or python3 on different systems.
Also, do not use:
#!/usr/local/bin/python
"python may be installed at /usr/bin/python or /bin/python in those
cases, the above #! will fail."
―"#!/usr/bin/env python" vs "#!/usr/local/bin/python"
It's really just a matter of taste. Adding the shebang means people can invoke the script directly if they want (assuming it's marked as executable); omitting it just means python has to be invoked manually.
The end result of running the program isn't affected either way; it's just options of the means.
Should I put the shebang in my Python scripts?
Put a shebang into a Python script to indicate:
this module can be run as a script
whether it can be run only on python2, python3 or is it Python 2/3 compatible
on POSIX, it is necessary if you want to run the script directly without invoking python executable explicitly
Are these equally portable? Which form is used most?
If you write a shebang manually then always use #!/usr/bin/env python unless you have a specific reason not to use it. This form is understood even on Windows (Python launcher).
Note: installed scripts should use a specific python executable e.g., /usr/bin/python or /home/me/.virtualenvs/project/bin/python. It is bad if some tool breaks if you activate a virtualenv in your shell. Luckily, the correct shebang is created automatically in most cases by setuptools or your distribution package tools (on Windows, setuptools can generate wrapper .exe scripts automatically).
In other words, if the script is in a source checkout then you will probably see #!/usr/bin/env python. If it is installed then the shebang is a path to a specific python executable such as #!/usr/local/bin/python (NOTE: you should not write the paths from the latter category manually).
To choose whether you should use python, python2, or python3 in the shebang, see PEP 394 - The "python" Command on Unix-Like Systems:
... python should be used in the shebang line only for scripts that are
source compatible with both Python 2 and 3.
in preparation for an eventual change in the default version of
Python, Python 2 only scripts should either be updated to be source
compatible with Python 3 or else to use python2 in the shebang line.
If you have more than one version of Python and the script needs to run under a specific version, the she-bang can ensure the right one is used when the script is executed directly, for example:
#!/usr/bin/python2.7
Note the script could still be run via a complete Python command line, or via import, in which case the she-bang is ignored. But for scripts run directly, this is a decent reason to use the she-bang.
#!/usr/bin/env python is generally the better approach, but this helps with special cases.
Usually it would be better to establish a Python virtual environment, in which case the generic #!/usr/bin/env python would identify the correct instance of Python for the virtualenv.
The purpose of shebang is for the script to recognize the interpreter type when you want to execute the script from the shell.
Mostly, and not always, you execute scripts by supplying the interpreter externally.
Example usage: python-x.x script.py
This will work even if you don't have a shebang declarator.
Why first one is more "portable" is because, /usr/bin/env contains your PATH declaration which accounts for all the destinations where your system executables reside.
NOTE: Tornado doesn't strictly use shebangs, and Django strictly doesn't. It varies with how you are executing your application's main function.
ALSO: It doesn't vary with Python.
You should add a shebang if the script is intended to be executable. You should also install the script with an installing software that modifies the shebang to something correct so it will work on the target platform. Examples of this is distutils and Distribute.
Sometimes, if the answer is not very clear (I mean you cannot decide if yes or no), then it does not matter too much, and you can ignore the problem until the answer is clear.
The #! only purpose is for launching the script. Django loads the sources on its own and uses them. It never needs to decide what interpreter should be used. This way, the #! actually makes no sense here.
Generally, if it is a module and cannot be used as a script, there is no need for using the #!. On the other hand, a module source often contains if __name__ == '__main__': ... with at least some trivial testing of the functionality. Then the #! makes sense again.
One good reason for using #! is when you use both Python 2 and Python 3 scripts -- they must be interpreted by different versions of Python. This way, you have to remember what python must be used when launching the script manually (without the #! inside). If you have a mixture of such scripts, it is a good idea to use the #! inside, make them executable, and launch them as executables (chmod ...).
When using MS-Windows, the #! had no sense -- until recently. Python 3.3 introduces a Windows Python Launcher (py.exe and pyw.exe) that reads the #! line, detects the installed versions of Python, and uses the correct or explicitly wanted version of Python. As the extension can be associated with a program, you can get similar behaviour in Windows as with execute flag in Unix-based systems.
When I installed Python 3.6.1 on Windows 7 recently, it also installed the Python Launcher for Windows, which is supposed to handle the shebang line. However, I found that the Python Launcher did not do this: the shebang line was ignored and Python 2.7.13 was always used (unless I executed the script using py -3).
To fix this, I had to edit the Windows registry key HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. This still had the value
"C:\Python27\python.exe" "%1" %*
from my earlier Python 2.7 installation. I modified this registry key value to
"C:\Windows\py.exe" "%1" %*
and the Python Launcher shebang line processing worked as described above.
Answer: Only if you plan to make it a command-line executable script.
Here is the procedure:
Start off by verifying the proper shebang string to use:
which python
Take the output from that and add it (with the shebang #!) in the first line.
On my system it responds like so:
$which python
/usr/bin/python
So your shebang will look like:
#!/usr/bin/python
After saving, it will still run as before since python will see that first line as a comment.
python filename.py
To make it a command, copy it to drop the .py extension.
cp filename.py filename
Tell the file system that this will be executable:
chmod +x filename
To test it, use:
./filename
Best practice is to move it somewhere in your $PATH so all you need to type is the filename itself.
sudo cp filename /usr/sbin
That way it will work everywhere (without the ./ before the filename)
If you have different modules installed and need to use a specific
python install, then shebang appears to be limited at first. However,
you can do tricks like the below to allow the shebang to be invoked
first as a shell script and then choose python. This is very flexible
imo:
#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; then
echo Using preferred python $PREFERRED_PYTHON
exec $PREFERRED_PYTHON "$0" "$#"
elif [ -x $ALTERNATIVE_PYTHON ]; then
echo Using alternative python $ALTERNATIVE_PYTHON
exec $ALTERNATIVE_PYTHON "$0" "$#"
else
echo Using fallback python $FALLBACK_PYTHON
exec python3 "$0" "$#"
fi
exit 127
'''
__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())
Or better yet, perhaps, to facilitate code reuse across multiple python scripts:
#!/bin/bash
"true" '''\'; source $(cd $(dirname ${BASH_SOURCE[#]}) &>/dev/null && pwd)/select.sh; exec $CHOSEN_PYTHON "$0" "$#"; exit 127; '''
and then select.sh has:
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; then
CHOSEN_PYTHON=$PREFERRED_PYTHON
elif [ -x $ALTERNATIVE_PYTHON ]; then
CHOSEN_PYTHON=$ALTERNATIVE_PYTHON
else
CHOSEN_PYTHON=$FALLBACK_PYTHON
fi
This is really a question about whether the path to the Python interpreter should be absolute or logical (/usr/bin/env) with respect to portability.
My view after thoroughly testing the behavior is that the logical path in the she-bang is the better of the two options.
Being a Linux Engineer, my goal is always to provide the most suitable, optimized hosts for my developer clients, so the issue of Python environments is something I really need a solid answer to. Encountering other answers on this and other Stack Overflow sites which talked about the issue in a general way without supporting proofs, I've performed some really granular testing & analysis on this very question on Unix.SE.
For files that are intended to be executable from the command-line, I would recommend
#! /usr/bin/env python3
Otherwise you don't need the shebang (though of course it doesn't harm).
If you use virtual environments like with pyenv it is better to write #!/usr/bin/env python
The pyenv setting will control which version of python and from which file location is started to run your script.
If your code is known to be version specific, it will help others to find why your script does not behave in their environment if you specify the expected version in the shebang.
If you want to make your file executable you must add shebang line to your scripts.
#!/usr/bin/env python3
is better option in the sense that this will not be dependent on specific distro of linux but could be used on almost all linux distro since it hunts for the python3 path from environment variables, which is different for different distros of linux.
whereas
#!/usr/local/bin/python3
would be a distro specific path for python3 and would not work if python3 is not found on this path, and could result in confusion and ambiguity for developer when migrating from one distro to another of linux.
Use first
which python
This will give the output as the location where my python interpreter (binary) is present.
This output could be any such as
/usr/bin/python
or
/bin/python
Now appropriately select the shebang line and use it.
To generalize we can use:
#!/usr/bin/env
or
#!/bin/env

How to select which version of python I am running on Linux?

The version of Linux I am working on has python 2.6 by default, and we installed 2.7 on it in a separate folder.
If I want to run a .py script, how do I tell it to use 2.7 instead of the default?
Use update-alternatives --config python and shoose python2.7 from choices.
If you need to remove it use update-alternatives --remove python /usr/bin/python2.7.
Sorry for "stealing" answers, but I feel that there is a little bit of chaos here.
There are different ways to achieve that, it depends on at what level the decision is taken.
System Level
[Credit to #WoLy]
Use the update-alternatives feature of the system. Specifically, use
$ update-alternatives --config python
and you can choose the specific version.
Result: Once you do this, everything that uses "python" will use the python2.7 binary. This will happen in the whole system, for all users.
User Level
This is a little bit trickier. Credit to #TheFlyingProgrammer
The basic approach would be to change the .bashrc file in order to change the path and/or add an alias. Problem is if you are relying on the "shebang" of the file:
#!/usr/bin/python
<code python here>
This kind of file will be unaffected of your changes. However:
#!/usr/bin/env python
<code python here>
or executions like
$ python name_of_script.py
will use the interpreter of choice (the one forced at the .bashrc file).
Result: The owner of the modified .bashrc file will use, by default, the interpreter of choice. But some sheband will behave differently. So it is a bit trickier. So, be cautious.
Script Level
[Credit to #Anony-Mousse]
The "shebang" approach, modifying the first line. The idea is using the full path in the first line of the python source file:
#!/usr/bin/python2.7
<code python here>
You can use python, python2 or python2.7 and you will be more or less specific in the version. The problem would be if you want it to be portable. A similar approach would be to use full specification of version but without path:
#!/usr/bin/env python2.7
<code python here>
Note that if the PATH is not correctly set, this won't work. This gives some power to the user (when setting the PATH). You can, for instance, choose #!/usr/bin/env python2 to force some Python 2.x flavour, but maybe the specific binary will change from user to user.
In addition to that, keep in mind that if you plan to use virtual environments, using /usr/bin/env python is advisable (if I'm not mistaken).
Result: Well, it depends whether you use the env binary or not. But, in any case, you are putting the semantic in the file, which makes sense in many cases (e.g. if there is an incompatibility, it is at the script level).
Execution Level
[Credit to #Prune]
This is the simplest approach:
$ /path/to/your/python/bin/python2.7 my_script.py
You change, for this specific execution, which binary will be using (the Python interpreter ignores the shebang, because it is a comment).
Result: You override all other choices by cherry-picking your Python binary. Very good approach to test behaviour, but not very maintainable or shareable.
If you require a particular version, use the full path.
If you have e.g. python2.7 and python3.4 installed (and this is very common, as they are not fully compatible):
A script with
#!/usr/bin/python
will usually be running the latest version of python2 because of comparibility reasons. **You should avoid overriding what /usr/bin/python points to, to not break your system. Some apps will require this to point to a compatible version.
Instead, use
#!/usr/bin/python3
to use the latest python 3
#!/usr/bin/python2.7
to require python2.7
If you manually installed python (why? use the packages, that is much smarter because of automatic upgrades) then use the full path!
~/my-python/bin/python myscript.py
or if you start your script with the shebang:
#!/home/whatever/my-python/bin/python
so you can +x your script and do simply
./myscript.py
or make yourself an alias such as py if you are lazy to type.
open ~/.bashrc with a text editor, and add alias python=/usr/local/bin/python2.7
In case you're using Cent OS as your linux distribution, you will notice that
sudo python <file.py> doesn't work. That's because sudo doesn't have /usr/local/bin as a secure path. Open /etc/sudoers with a text editor, and you should see
#
# Adding HOME to env_keep may enable a user to run unrestricted
# commands via sudo.
#
# Defaults env_keep += "HOME"
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
Add :/usr/local/bin to that secure_path and save.

Should I put #! (shebang) in Python scripts, and what form should it take?

Should I put the shebang in my Python scripts? In what form?
#!/usr/bin/env python
or
#!/usr/local/bin/python
Are these equally portable? Which form is used most?
Note: the tornado project uses the shebang. On the other hand the Django project doesn't.
The shebang line in any script determines the script's ability to be executed like a standalone executable without typing python beforehand in the terminal or when double clicking it in a file manager (when configured properly). It isn't necessary but generally put there so when someone sees the file opened in an editor, they immediately know what they're looking at. However, which shebang line you use is important.
Correct usage for (defaults to version 3.latest) Python 3 scripts is:
#!/usr/bin/env python3
Correct usage for (defaults to version 2.latest) Python 2 scripts is:
#!/usr/bin/env python2
The following should not be used (except for the rare case that you are writing code which is compatible with both Python 2.x and 3.x):
#!/usr/bin/env python
The reason for these recommendations, given in PEP 394, is that python can refer either to python2 or python3 on different systems.
Also, do not use:
#!/usr/local/bin/python
"python may be installed at /usr/bin/python or /bin/python in those
cases, the above #! will fail."
―"#!/usr/bin/env python" vs "#!/usr/local/bin/python"
It's really just a matter of taste. Adding the shebang means people can invoke the script directly if they want (assuming it's marked as executable); omitting it just means python has to be invoked manually.
The end result of running the program isn't affected either way; it's just options of the means.
Should I put the shebang in my Python scripts?
Put a shebang into a Python script to indicate:
this module can be run as a script
whether it can be run only on python2, python3 or is it Python 2/3 compatible
on POSIX, it is necessary if you want to run the script directly without invoking python executable explicitly
Are these equally portable? Which form is used most?
If you write a shebang manually then always use #!/usr/bin/env python unless you have a specific reason not to use it. This form is understood even on Windows (Python launcher).
Note: installed scripts should use a specific python executable e.g., /usr/bin/python or /home/me/.virtualenvs/project/bin/python. It is bad if some tool breaks if you activate a virtualenv in your shell. Luckily, the correct shebang is created automatically in most cases by setuptools or your distribution package tools (on Windows, setuptools can generate wrapper .exe scripts automatically).
In other words, if the script is in a source checkout then you will probably see #!/usr/bin/env python. If it is installed then the shebang is a path to a specific python executable such as #!/usr/local/bin/python (NOTE: you should not write the paths from the latter category manually).
To choose whether you should use python, python2, or python3 in the shebang, see PEP 394 - The "python" Command on Unix-Like Systems:
... python should be used in the shebang line only for scripts that are
source compatible with both Python 2 and 3.
in preparation for an eventual change in the default version of
Python, Python 2 only scripts should either be updated to be source
compatible with Python 3 or else to use python2 in the shebang line.
If you have more than one version of Python and the script needs to run under a specific version, the she-bang can ensure the right one is used when the script is executed directly, for example:
#!/usr/bin/python2.7
Note the script could still be run via a complete Python command line, or via import, in which case the she-bang is ignored. But for scripts run directly, this is a decent reason to use the she-bang.
#!/usr/bin/env python is generally the better approach, but this helps with special cases.
Usually it would be better to establish a Python virtual environment, in which case the generic #!/usr/bin/env python would identify the correct instance of Python for the virtualenv.
The purpose of shebang is for the script to recognize the interpreter type when you want to execute the script from the shell.
Mostly, and not always, you execute scripts by supplying the interpreter externally.
Example usage: python-x.x script.py
This will work even if you don't have a shebang declarator.
Why first one is more "portable" is because, /usr/bin/env contains your PATH declaration which accounts for all the destinations where your system executables reside.
NOTE: Tornado doesn't strictly use shebangs, and Django strictly doesn't. It varies with how you are executing your application's main function.
ALSO: It doesn't vary with Python.
You should add a shebang if the script is intended to be executable. You should also install the script with an installing software that modifies the shebang to something correct so it will work on the target platform. Examples of this is distutils and Distribute.
Sometimes, if the answer is not very clear (I mean you cannot decide if yes or no), then it does not matter too much, and you can ignore the problem until the answer is clear.
The #! only purpose is for launching the script. Django loads the sources on its own and uses them. It never needs to decide what interpreter should be used. This way, the #! actually makes no sense here.
Generally, if it is a module and cannot be used as a script, there is no need for using the #!. On the other hand, a module source often contains if __name__ == '__main__': ... with at least some trivial testing of the functionality. Then the #! makes sense again.
One good reason for using #! is when you use both Python 2 and Python 3 scripts -- they must be interpreted by different versions of Python. This way, you have to remember what python must be used when launching the script manually (without the #! inside). If you have a mixture of such scripts, it is a good idea to use the #! inside, make them executable, and launch them as executables (chmod ...).
When using MS-Windows, the #! had no sense -- until recently. Python 3.3 introduces a Windows Python Launcher (py.exe and pyw.exe) that reads the #! line, detects the installed versions of Python, and uses the correct or explicitly wanted version of Python. As the extension can be associated with a program, you can get similar behaviour in Windows as with execute flag in Unix-based systems.
When I installed Python 3.6.1 on Windows 7 recently, it also installed the Python Launcher for Windows, which is supposed to handle the shebang line. However, I found that the Python Launcher did not do this: the shebang line was ignored and Python 2.7.13 was always used (unless I executed the script using py -3).
To fix this, I had to edit the Windows registry key HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. This still had the value
"C:\Python27\python.exe" "%1" %*
from my earlier Python 2.7 installation. I modified this registry key value to
"C:\Windows\py.exe" "%1" %*
and the Python Launcher shebang line processing worked as described above.
Answer: Only if you plan to make it a command-line executable script.
Here is the procedure:
Start off by verifying the proper shebang string to use:
which python
Take the output from that and add it (with the shebang #!) in the first line.
On my system it responds like so:
$which python
/usr/bin/python
So your shebang will look like:
#!/usr/bin/python
After saving, it will still run as before since python will see that first line as a comment.
python filename.py
To make it a command, copy it to drop the .py extension.
cp filename.py filename
Tell the file system that this will be executable:
chmod +x filename
To test it, use:
./filename
Best practice is to move it somewhere in your $PATH so all you need to type is the filename itself.
sudo cp filename /usr/sbin
That way it will work everywhere (without the ./ before the filename)
If you have different modules installed and need to use a specific
python install, then shebang appears to be limited at first. However,
you can do tricks like the below to allow the shebang to be invoked
first as a shell script and then choose python. This is very flexible
imo:
#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; then
echo Using preferred python $PREFERRED_PYTHON
exec $PREFERRED_PYTHON "$0" "$#"
elif [ -x $ALTERNATIVE_PYTHON ]; then
echo Using alternative python $ALTERNATIVE_PYTHON
exec $ALTERNATIVE_PYTHON "$0" "$#"
else
echo Using fallback python $FALLBACK_PYTHON
exec python3 "$0" "$#"
fi
exit 127
'''
__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())
Or better yet, perhaps, to facilitate code reuse across multiple python scripts:
#!/bin/bash
"true" '''\'; source $(cd $(dirname ${BASH_SOURCE[#]}) &>/dev/null && pwd)/select.sh; exec $CHOSEN_PYTHON "$0" "$#"; exit 127; '''
and then select.sh has:
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; then
CHOSEN_PYTHON=$PREFERRED_PYTHON
elif [ -x $ALTERNATIVE_PYTHON ]; then
CHOSEN_PYTHON=$ALTERNATIVE_PYTHON
else
CHOSEN_PYTHON=$FALLBACK_PYTHON
fi
This is really a question about whether the path to the Python interpreter should be absolute or logical (/usr/bin/env) with respect to portability.
My view after thoroughly testing the behavior is that the logical path in the she-bang is the better of the two options.
Being a Linux Engineer, my goal is always to provide the most suitable, optimized hosts for my developer clients, so the issue of Python environments is something I really need a solid answer to. Encountering other answers on this and other Stack Overflow sites which talked about the issue in a general way without supporting proofs, I've performed some really granular testing & analysis on this very question on Unix.SE.
For files that are intended to be executable from the command-line, I would recommend
#! /usr/bin/env python3
Otherwise you don't need the shebang (though of course it doesn't harm).
If you use virtual environments like with pyenv it is better to write #!/usr/bin/env python
The pyenv setting will control which version of python and from which file location is started to run your script.
If your code is known to be version specific, it will help others to find why your script does not behave in their environment if you specify the expected version in the shebang.
If you want to make your file executable you must add shebang line to your scripts.
#!/usr/bin/env python3
is better option in the sense that this will not be dependent on specific distro of linux but could be used on almost all linux distro since it hunts for the python3 path from environment variables, which is different for different distros of linux.
whereas
#!/usr/local/bin/python3
would be a distro specific path for python3 and would not work if python3 is not found on this path, and could result in confusion and ambiguity for developer when migrating from one distro to another of linux.
Use first
which python
This will give the output as the location where my python interpreter (binary) is present.
This output could be any such as
/usr/bin/python
or
/bin/python
Now appropriately select the shebang line and use it.
To generalize we can use:
#!/usr/bin/env
or
#!/bin/env

Categories