1213

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.

Mike T
  • 41,085
  • 18
  • 152
  • 203
treecoder
  • 43,129
  • 22
  • 67
  • 91
  • 106
    The second one is not portable and *will* fail on many computers, if not most. – Dietrich Epp Aug 02 '11 at 06:46
  • 9
    How does `#!/usr/bin/python` compare to the first option? I see this in quite a lot of example code. Edit: Maybe this is the answer.. http://stackoverflow.com/a/2429517/1156245 – geotheory Nov 29 '14 at 14:30
  • 1
    possible duplicate of [Why do people write #!/usr/bin/env python on the first line of a Python script?](http://stackoverflow.com/questions/2429511/why-do-people-write-usr-bin-env-python-on-the-first-line-of-a-python-script) – nbro Jul 05 '15 at 02:22
  • 1
    I say always use it, Why? "Zen Of Python" - Line 2 - "Explicit is better than implicit." https://www.python.org/dev/peps/pep-0020/ – JayRizzo May 10 '18 at 04:25
  • 4
    Frankly, neither is "right", because you as the author don't know where the correct version of Python will be when the script is run. It should be the job of the *installer* to add the correct shebang. – chepner Jun 03 '18 at 01:24
  • 10
    @JayRizzo: there's a difference between fixed/configurable and implicit/explicit. `/usr/bin/env python` **is** explicit, and means _"use the environment's default python"_, allowing pip/user/OS/local admin/virtualenv to select one via `$PATH`, while `/usr/bin/python` _forces_ the OS-selected python – MestreLion Nov 05 '19 at 11:48
  • 2
    @chepner: while it's true it's the installer's job to select the correct python, it should not do so by source-editing a shebang, but rather by manipulating `$PATH` and the environment. – MestreLion Nov 05 '19 at 11:51

15 Answers15

1640

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"

LeopardShark
  • 3,820
  • 2
  • 19
  • 33
GlassGhost
  • 16,906
  • 5
  • 32
  • 45
  • 127
    @Dunes: `env` will ***always*** be found in `/usr/bin/`, and its job is to locate bins (like python) using `PATH`. No matter how python is installed, its path will be added to this variable, and `env` will find it (if not, python is not installed). That's the job of `env`, that's the whole _reason_ why it exists. It's the thing that alerts the environment (set up env variables, including the install paths, and include paths). People have always understood that this command can only work if it's always found in the same place. That's just a given – Elias Van Ootegem Dec 17 '14 at 15:59
  • 3
    `#!/usr/bin/env python3` does not work in window10. `#!/usr/bin/env python` works in both Windows10 & ubuntu – Daniel Pinyol Nov 30 '21 at 12:49
  • @DanielPinyol What if I have both Python 2 and 3? How do I force it to use Python3 on Windows 10? – Tomerikoo Dec 26 '21 at 23:08
  • 1
    Debian Bullseye has no `python` by default. Using `python2` or `python3` explicitly is recommended. There are packages `python-is-python2` and `python-is-python3` that add the `python` command again. Python 2 is unmaintained since 2020-01-01 so migration to Python 3 is a necessity. https://wiki.debian.org/Python – Palec Dec 29 '21 at 15:54
  • @DanielPinyol, according to the official docs, `#!/usr/bin/env python3` should work when used through py.exe. https://docs.python.org/3/using/windows.html#shebang-lines https://learn.microsoft.com/en-us/windows/python/faqs#what-is-py-exe- – Palec Dec 29 '21 at 15:59
  • What''s the difference between `/usr/bin/env python3` and just `python3`? Isn't the path searched anyway when running a command? – kristianp Jul 18 '22 at 01:46
  • 1
    @kristianp On Unix/Linux, the PATH is never searched when the OS runs an interpreter via the shebang mechanism (i.e. when executing a “script”). On Windows, which does not have this mechanism, there is a registered “launcher” for .py files which interprets the shebang line in a “private” way as [documented](https://docs.python.org/3/using/windows.html#shebang-lines). – Robert Siemer Jan 06 '23 at 13:06
  • @DanielPinyol According to the doc `#!/usr/bin/env python3` will search for a `python3.exe` from `PATH`. However, it seems that the Python installer from the official site doesn't create a python3 executable, while the Python installed through Windows Store does. Unfortunately the latter is usually an outdated version. I personally install the former and create a symbolic link of `python3.exe` that points to the installed `python.exe` in the same directory (through the `mklink` command) to workaround the issue. – Danny Lin Feb 28 '23 at 16:30
99

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.

Amber
  • 507,862
  • 82
  • 626
  • 550
  • i know that -- but since some projects do it and some don't -- i was wondering what side should i take for a big python project -- and would this decision really matter in long term? – treecoder Aug 02 '11 at 06:43
  • 6
    That's just it - it doesn't matter what side you take because there isn't a "right" side. It's a completely subjective decision. – Amber Aug 02 '11 at 06:45
  • 6
    No more than any other trivial decision. http://en.wikipedia.org/wiki/Parkinson's_Law_of_Triviality – Amber Aug 02 '11 at 06:50
  • 2
    How could I execute a python file directly without 'python' command? – Zen Jun 17 '14 at 10:55
  • 10
    @Zen Assuming you included the shebang (#!/usr/bin/env python) in your script you just need to make your script executable. Something like `chmod a+x [your-script].py` should make it executable and then you can just call `./[your-script.py]` in shell. – skålfyfan Oct 06 '14 at 22:01
  • 20
    As the answer by GlassGhost points out, there *is* a concrete advantage to including it besides taste: it makes clear to a future reader of the file that they're reading an executable script, rather than a file that's meant to be imported. Similarly to public/private access control modifiers in languages that have them, shebangs are useful as *documentation* as well as for their actual effect, and in some cases the documentation aspect actually matters most. – Mark Amery Dec 20 '14 at 19:42
  • 6
    Isn't that what `if __name__ == "__main__":` is for? – Dan Aug 11 '15 at 01:23
  • 1
    If you're distributing the program to others who aren't necessarily programmers, it's a good idea to use the shebang line, so they can execute the file transparently of being python aware. – user12711 Mar 28 '17 at 19:00
44

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.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • 3
    The first answer to even refer to a PEP doesn’t have enough upvotes. Huh? Is there a PEP for `#!/usr/bin/env python` itself? – binki Sep 24 '15 at 20:03
  • 1
    Please don't use `#!/usr/bin/env python`. Please don't suggest to "always use" `#!/usr/bin/env python`. This is the wrong thing to do in 99% of cases (the reason which you've included in your answer). – Jay Sullivan Aug 14 '19 at 02:33
  • 1
    @JaySullivan do you understand the difference between a source checkout and installed scripts? I stand behind the suggestion. It works well. – jfs Aug 14 '19 at 03:27
  • 3
    @jfs: After re-reading my comment I see how I utterly failed to get my point across. What I meant was that most people will want to use 'python2' or 'python3', not 'python'. Whether or not to resolve via full path or env, which technically was the OP question, you've answered and I don't disagree on that point. – Jay Sullivan Aug 15 '19 at 16:57
  • @JaySullivan I agree. Did you read the quote from the pep in the answer. It says the same thing. – jfs Aug 15 '19 at 17:00
21

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.

Mike T
  • 41,085
  • 18
  • 152
  • 203
Chris Johnson
  • 20,650
  • 6
  • 81
  • 80
  • 1
    Isn't the space going to cause it to fail? – RandomInsano Jan 28 '14 at 15:42
  • 1
    @RandomInsano, I don't think so. Spaces seem pretty common and there is a lot of evidence around the 'net of this as an accepted usage. However I think no-space is probably the more canonical usage. – Chris Johnson Jan 29 '14 at 19:25
  • 1
    You're definitely right on this one. Just tested on bash and tcsh. – RandomInsano Jan 30 '14 at 16:42
  • The results of `which` will give you a string that will work, period. You don't need to worry about any of the guts in order to use it. – SDsolar Oct 17 '17 at 10:15
15

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.

Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
meson10
  • 1,934
  • 14
  • 21
14

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.

pepr
  • 20,112
  • 15
  • 76
  • 139
13

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.

Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
  • 1
    You don't have to modify the #! line afterwards. That's what /usr/bin/env is for. Hard-coding against a specific Python interpreter may do more harm than good. It is very fragile regarding installing another Python version or switching between our distro's Python versus a custom Python installation. – vog Jan 31 '15 at 10:03
  • In Ubuntu, using the results of `which` will automatically pick the default that is being used by system commands and such. It is generic and the system steers it to the proper installation. – SDsolar Oct 17 '17 at 10:14
9

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.

ETalbot
  • 91
  • 1
  • 1
  • From the description, it seems the issue was not that Python Launcher ignored the shebang. The issue was that **Python Launcher was installed but not used due to the system's configuration**. – Palec Dec 29 '21 at 16:37
8

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)

SDsolar
  • 2,485
  • 3
  • 22
  • 32
  • I doubt that this is best practice and I strongly recommend using [GlassGhost's solution](https://stackoverflow.com/a/19305076/2648551). – colidyre Jun 25 '19 at 11:16
  • I found this helpful and it worked beautifully for me. this was well explained. I would appreciate comments indicating why this isn't a best practice, however. I'm eager to learn. – Charles Carriere Jan 24 '20 at 03:32
  • I found this is well explained than GlassGhosts' solution, except shebang format. The better shebang format is: #!/usr/bin/env python3 – Dylan Wang Mar 01 '21 at 06:58
  • This helped tremendously since I was trying to use Python on MobaXterm and it isn't a typical linux/unix setup! – kuroikenshi Nov 05 '21 at 21:59
  • If it is a stand-alone script this answer is to the point. If the file is just an entry point of a larger program, I would definitely prefer creating a symbolic link to copying. – Palec Dec 29 '21 at 16:34
8

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
Beni Cherniavsky-Paskin
  • 9,483
  • 2
  • 50
  • 58
Goblinhack
  • 2,859
  • 1
  • 26
  • 26
  • 3
    While I'm not sure that a polyglot like this is good practice in general, it's certainly very interesting approach, and probably the most flexible answer here. – Ryan Amos Feb 29 '20 at 19:26
3

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.

Palec
  • 12,743
  • 8
  • 69
  • 138
F1Linux
  • 3,580
  • 3
  • 25
  • 24
2

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).

mara004
  • 1,435
  • 11
  • 24
1

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.

dejanualex
  • 3,872
  • 6
  • 22
  • 37
1

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.

-3

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
frp farhan
  • 445
  • 5
  • 19
  • 3
    This will most probably not be portable to other systems. `#!/usr/bin/env` makes the right choice for you. – fragmentedreality Mar 09 '17 at 12:49
  • That's why you use the `which` command - it will return the correct string for your particular system. – SDsolar Oct 17 '17 at 10:12
  • 1
    ... and then everytime the script is to be executed on another machine, you run `which python` again and change the script if the output differs from the current shebang – fragmentedreality Jan 09 '18 at 19:16
  • 3
    -1 This is the most fragile possible solution. It is only guaranteed to be correct for the system on which your python script is written. Use #!/usr/bin/env python3 for portability – Myles Hollowed Jan 31 '18 at 07:55