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
In the pip program, the She-bang is
#!/usr/local/bin/python
if __name__ == "__main__":
# Python program body
while in the Install Certificates.command that Python Launcher offers:
#!/bin/sh
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 << "EOF"
# python program body
EOF
Are there any differences between those two approaches? And is there any reason to prefer one to another?
It seems to me they are all the same, except for the second one has one more bash subroutine. Is this right?
In the general case, you simply want to specify the interpreter you actually want.
Outside of this, you sometimes see workarounds like this as portability hacks. On POSIX systems, /usr/bin/env covers the majority of scenarios quite nicely; but if you need portability to older or otherwise peculiar systems, falling back to the lowest common denominator and then working your way back up to a place where you can reliably run e.g. Python on a variety of systems may require all kinds of unobvious constructs. (The previous - upvoted! - answer by Dan D. is a good example.)
There are also cases where you want sh to set something up (fetch some environment variables which are specified in a file which uses sh syntax, for example) and then hand over execution to Python;
#!/bin/sh
# source some variables
. /etc/defaults/myenv.sh
# Then run Python
exec env python -c '
# ... Your Python script here
' "$#"
There is a line length limit on the #! line. Perhaps they did that to get around that.
The options are the path to the program but only if it is short enough. Use of env python which uses the path. Or chain loading like this.
This specific code for the Install Certificates.command script was introduced in Python Issue #17128. As far as I can tell, the author hasn't explained why he wrote the code this way.
Note that .command files are Shell scripts on Mac OS X that can be executed by double-clicking on them in Finder.
I believe the likely explanation is that the author simply wanted to honour Mac OS X's expectation that .command files should be Shell scripts.
You could test this by placing the following content in a file ~/Desktop/test.command:
#!/usr/bin/env python
print "Hello world"
Then view the Desktop folder in Finder, and note that it is reported as a "shell" file:
(Although it is reported incorrectly as a Shell file, this Python script can still be executed by double-clicking on it. It doesn't break Finder or anything.)
To answer the specific question, one reason for preferring this pattern might be, as Dan D. said, to avoid a Shebang line limit.
In general, you would prefer to use #!/usr/bin/env python as your Shebang line. Creating a Bash Heredoc (i.e. the python3.6 << EOF pattern) would create all sorts of problems, such as your syntax highlighting won't work, you have to watch out for Bash variable interpolation inside the Heredoc, etc.
I am creating a setup from C# program successfully with Inno Setup. To run this program I need Python. Until today I asked my customers to install Python manually, since some customers are not always following my installation guide, I am getting often questions from them. Now I want to simplify the installation, so that everything is done automatically. I need to set:
Install path of Python: C:\Python\Python3.5.2
Installation for all users
Set the global environment variable for Python C:\Python\Python3.5.2
If all this already exist no installation needed
I tried to do this with this code, but I didn't had any success. Normal Python installation is starting unfortunately.
[Run]
Filename: "{app}\deploy\python-3.5.2.exe"; \
Parameters: "/i ""C:\Python\Python-3.5.2"" /qb! ALLUSER=1 ADDLOCAL=ALL"; \
WorkingDir: "{app}\deploy"; Flags: 32bit; Check: python_is_installed
[Code]
function python_is_installed() : Boolean;
var
key : string;
begin
{ check registry }
key := 'software\Python\Python-3.5.2\InstallPath';
Result := not RegValueExists(HKEY_LOCAL_MACHINE, Key, '');
end;
What do I do wrong?
BR
Stefan
You seem to be using a completely wrong sent of command line arguments (for Windows Installer?).
See Python documentation for correct command-line arguments of the Python Windows installer:
https://docs.python.org/3/using/windows.html
You probably want something like this:
/passive InstallAllUsers=1 TargetDir=C:\Python\Python3.5.2 PrependPath=1
Another problem is that the installation check in the code section is not working as expected. RegValueExists() always returns false with an empty value name. That means your check function always returns false even if the key exists. This is the reason why Python installation is run always, even if Python is already installed.
To check for the existence of a key, not a value, use the function RegKeyExists().
See How to check if specific Python version is installed in Inno Setup?
I am quite new with configuring Jenkins or Python but I have to set up a unitary test in Jenkins. My program is in Python, but only works on Python 2.6 whereas the Jenkins version I should be using is 2.7, so I'm trying to set up Jenkins to set some environment variables so that it prepares launching the accurate Python for that specific test (it is part of a greater project that will successfully run several other tests that work well).
The idea I had was to set in the command to execute several environment variables like PATH, LD_LIBRARY_PATH and PYTHONPATH such as following in the "Execute shell" command line interpreter:
PYTHONPATH=/path/to/python2.6/lib:$PYTHONPATH
PATH=/path/to/python2.6/bin:$PATH
LD_LIBRARY_PATH=/path/to/python2.6/lib:$LD_LIBRARY_PATH
... however, it was still calling the wrong version of Python. Therefore, I forced these variables to:
PYTHONPATH=/path/to/python2.6/lib
PATH=/path/to/python2.6/bin
LD_LIBRARY_PATH=/path/to/python2.6/lib
... and I still get errors because the old version of Python is called instead, even if it should not appear in the PATH ... It appears Jenkins will remember the location of the old libraries however and will try loading them first.
How would I correctly set the environment in a "subproject" in Jenkins so that I can call a different version of Python?
Thank you and best regards,
~Stéphane
If you want your program to run with a specific version of the python interpreter, you indicate it in the shebang
#!/usr/bin/python2.6
#your code here
What i did in my Jenkins shell script using a specific python version was something like this when calling my unit test:
python3 src/test/unit_test.py
I was using it to use Python 3.X but it should work with 2.6 as well using:
python2.6 src/test/unit_test.py
Stupid me... I was indeed doing things correctly, I just had a part of my code that was overriding the PYTHONPATH value, so the solution I had found previously was good.
FYI, I modified my shebang, if it's of any help to anyone ;)
I use Python 2.6 more than I use Leopard's default python installation, so I have it set as my main Python installation. But I'd rather use the default Python for a PyObjC program I'm working on. Is there any way to specify to only use it instead of Python 2.6?
Finally figured this one out myself. The key to this is to make the final executable link with /System/Library/Frameworks/Python.framework instead of /Library/Frameworks/Python.framework.
Try specifying the full path to the Python interpreter in the command line, something like:
/foo/bar/python2.6 script.py
/baz/python objcscript.py
You can also add a shebang to the beginning of your script (first line):
#! /foo/bar/python2.6 script.py
If you have the environment variable PYTHONPATH set, you might have to unset it or change it.
AFAIR this helped me (in main.m):
NSArray *pythonPathArray = [NSArray arrayWithObjects: resourcePath, [resourcePath stringByAppendingPathComponent:#"PyObjC"], #"/System/Library/Frameworks/Python.framework/Versions/Current/Extras/lib/python/", #"/Library/Python/2.5/site-packages", nil];
Also, make sure that this point to the Python installation you want to use (main.m):
Py_SetProgramName("/usr/bin/python");