Why Do People Write #!/Usr/Bin/Env Python on the First Line of a Python Script

What is the advantage of #!/usr/bin/env python in the shebang rather than just calling the #!python interpreter?

Short answer:
This depends on the shell. in bash #!python will just be ignored and you have to use #!/usr/bin/env python. zsh on the other hand seems to be able to handle #!python.

The long answer (for bash):

let's imagine your python file is named 'tst.py'
and has following contents

#!python
import sys
print(sys.executable, sys.version)

then you can always type

python tst.py

The first line is completely irrelevant and is not even looked at.

However if you do following (for example on linux)

chmod +x tst.py
./tst.py

Then the first line is looked at to determine which interpreter shall be used (bash, perl, python, something else?) and here at least for my OS (ubuntu) and my shell (bash) an absolute path is required for the executable name (e.g. /bin/bash, /bin/python, /usr/bin/env)

If I call ./tst.py on my ubuntu machine I get

bash: ./tst.py: python: bad interpreter: No such file or directory

Special case Windows, when typing tst.py or clicking on a python script.
If you're on windows, the line is looked at, but even if it is wrong a default python interpreter will be used. On Windows, this line could be used to select explicitly python2 or python3 for example.
Windows uses file type associations to determine which executable to call for which suffix. for .py files (python 3.x is installed) this is normally py.exe which is an executable located in the system path, that will just call a python interpreter. depending on installed versions, the shebang line and environment vars, that might indicate a virtualenv

Addendum:
The first line is interpreted by the shell or in the windows case by py.exe.

It seems bash requires absolute paths for command, whereas zsh accepts relative paths as well.

So for zsh only

#!python

works perfectly well whereas bash requiers absolute paths and thus the trick with the env command

#!/usr/bin/env python

For scripts that shall be executed by a cronjob it's best to hardcode the path of the python executable as PATH is rather minimalistic for cronjobs, so there it's best to have something like

#!/usr/bin/python3.5

or

#!/home/username/myvirtualenv/bin/python

Purpose of #!/usr/bin/python3 shebang

#!/usr/bin/python3 is a shebang line.

A shebang line defines where the interpreter is located. In this case, the python3 interpreter is located in /usr/bin/python3. A shebang line could also be a bash, ruby, perl or any other scripting languages' interpreter, for example: #!/bin/bash.

Without the shebang line, the operating system does not know it's a python script, even if you set the execution flag (chmod +x script.py) on the script and run it like ./script.py. To make the script run by default in python3, either invoke it as python3 script.py or set the shebang line.

You can use #!/usr/bin/env python3 for portability across different systems in case they have the language interpreter installed in different locations.

Is '#!/usr/bin/python' in front of every Python script a must?

If the script is made executable, the operating system will use that first line to know which interpreter to run to parse the rest of the file to perform some action.

If you always run these kinds of scripts from the command line like python foo.py then you could remove the first line.

Why is '#!/usr/bin/env python' supposedly more correct than just '#!/usr/bin/python'?

If you're prone to installing python in various and interesting places on your PATH (as in $PATH in typical Unix shells, %PATH on typical Windows ones), using /usr/bin/env will accomodate your whim (well, in Unix-like environments at least) while going directly to /usr/bin/python won't. But losing control of what version of Python your scripts run under is no unalloyed bargain... if you look at my code you're more likely to see it start with, e.g., #!/usr/local/bin/python2.5 rather than with an open and accepting #!/usr/bin/env python -- assuming the script is important I like to ensure it's run with the specific version I have tested and developed it with, NOT a semi-random one;-).

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

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"

#!/usr/bin/python and #!/usr/bin/env python, which support?

The Debian Python Policy states:

The preferred specification for the Python interpreter is /usr/bin/python or /usr/bin/pythonX.Y. This ensures that a Debian installation of python is used and all dependencies on additional python modules are met.

Maintainers should not override the Debian Python interpreter using /usr/bin/env python or /usr/bin/env pythonX.Y. This is not advisable as it bypasses Debian's dependency checking and makes the package vulnerable to incomplete local installations of python.

Note that Debian/Ubuntu use the alternatives system to manage which version /usr/bin/python actually points to. This has been working very nicely across a lot of python versions at least for me (and I've been using python from 2.3 to 2.7 now), with excellent transitions across updates.

Note that I've never used pip. I want automatic security upgrades, so I install all my python needs via aptitude. Using the official Debian/Ubuntu packages keep my system much cleaner than me messing around with the python installation myself.


Let me emphasize one thing. The above recommendation refers to system installation of python applications. It makes perfectly sense to have these use the system managed version of python. If you are actually playing around with your own, customized installation of python that is not managed by the operating system, using the env variant probably is the correct way of saying "use the user-preferred python", instead of hard-coding either the system python installation (which would be /usr/bin/python) or any user-custom path.

Using env python will cause your programs to behave differently if you call them from e.g. a python virtualenv.

This can be desired (e.g. you are writing a script to work only in your virtualenv). And it can be problematic (you write a tool for you, and expect it to work the same even within a virtualenv - it may suddenly fail because it is missing packages then).

What's the difference between python shebangs with /usr/bin/env rather than hard-path?

#!/usr/bin/python is hardcoded to always run /usr/bin/python, while #!/usr/bin/env python will run whichever python would be default in your current environment (it will take in account for example $PATH, you can check which python interpreter will be used with which python).

The second way ( #!/usr/bin/env python ) is preferred , as it's not dependent on particular installation. It will work for example with virtualenv setups or systems where there is no /usr/bin/python, but only e.g. /usr/local/bin/python.



Related Topics



Leave a reply



Submit