Should I Put #! (Shebang) in Python Scripts, and What Form Should It Take

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"

Proper shebang for Python script

#!/usr/bin/env python

is more portable because in general the program /usr/bin/env can be used to "activate" the desired command without full path.

Otherwise, you would have to specify the full path of the Python interpreter, which can vary.

So no matter if the Python interpreter was in /usr/bin/python or in /usr/local/bin/python or in your home directory, using #!/usr/bin/env python will work.

Should I put the shebang line in every python file?

Only files which you will execute by invoking them directly require the shebang. Small hint: if a file contains

if __name__ == "__main__":
main()

it is better (to stick with the Least Astonishment principle) to start it with a shebang. Make sure to have that shebang robust; rather have

#!/usr/bin/env python

than

#!/usr/bin/python

Many module files contain a main method used to start tests, so many module files start with a shebang.

What shebang should I use to consistently point to python3?

Unfortunately, there is no universally working way of doing this that would work across any and all up front unknown Linux hosts and you are largely left at the mercy of distro maintainers and local host configuration.

alias won't help, because interpreter specified by #! handled by the kernel and /usr/bin/env it will exec in this case does not know about aliases of your shell.

When using env, you could make sure that the name following env is first found and means what you want it to mean by:

  • making sure all hosts are setup the same way in that respect (expected packaged are installed or at least symlinks are created)
  • having user specific construct for execution of your script, such as:
    mkdir /tmp/bin
    ln -s /usr/bin/python /tmp/bin/python3
    PATH="/tmp/bin:${PATH}" ./myscript.py

But none of this is really great and ultimately what you've asked for.

Your interpreter (this is harder than it may sound though, interpreter resolution code is quite simple; where to put it, how to call it for kernel to find and use it) could also be a simple shell script that tries to figure it out that you pack with your python code, but any option you look at isn't really great I am afraid.

There is a PEP-394 for that which suggested / expected on U*X-like system:

  • you get python for python2
  • and python3 for python3

But it recognizes this has never been entirely consistently applied... and also not as useful in 2020:

However, these recommendations implicitly assumed that Python 2 would always be available. As Python 2 is nearing its end of life in 2020 (PEP 373, PEP 404), distributions are making Python 2 optional or removing it entirely. This means either removing the python command or switching it to invoke Python 3. Some distributors also decided that their users were better served by ignoring the PEP's original recommendations, and provided system administrators with the freedom to configure their systems based on the needs of their particular environment.

TL;DR unfortunately there is no way that universally works and compensates for decisions of various distro and even individual host maintainers. :(

I would most likely opt to stick with #!/usr/bin/env python3 (which has so far been the recommended naming) and add a README that explains the prerequisites and how to setup the host just to be sure.


For the sake of completeness I should add, the PEP does make a recommendation in this regard: setup and use virtual environment or use a (third party) environment manager. However the way I read the question: "Portable interpreter specification that does not make any assumptions about nor poses any (additional) requirements to target host configuration", this would then not fit the bill and would not mean a substantial improvement over saying: make sure you have python3 executable in the search path and create a symlink if not.

Python - what is the shebang line supposed to do if the stated version is not installed ?? what if shebang is not the first line?

The shebang is what will be run if the script is run with chmod +x test.py and then ./test.py. Then the shell (i.e. bash) will run /usr/bin/env python2 test.py. However, when you explicitly use python3 test.py the shell will not check your shebang, it will just run python3.

Also, if you put the shebang at any line other than the first, it is no longer a shebang. Quoting Wikipedia:

In computing, a shebang is the character sequence consisting of the characters number sign and exclamation mark (#!) at the beginning of a script.

The shsebang can only be at the biginning. If it is not then the shell will not look at it, so it ran test.py as a shell script, where many commands are not found.

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.

Proper shebang of python script running on Windows

The interpretation of the shebang lines on Linux (and Unix like machines) is done by the operating system, and Windows doesn't do that, so there is no proper shebang line.

So if you don't want to do something special like selecting a particular Python version for your program, you can leave out the shebang (or leave in the one you need for running on Linux).

If your .py files are registered on Windows to be started by a particular Python executable, it is possible to check the first line of that file and interpret it to make sure you start the right version.

It is possible to start another Python version in that way with the original file and other arguments, but keep in mind that if you use that to start e.g a Python 2.7 interpreter where Python 3.8 is the one registered, that your Python program must be valid Python for both versions (so no print statements, f'{somevar}' strings, etc.)



Related Topics



Leave a reply



Submit