When I use the shebang #!/usr/bin/env python to run a script, how does the system know which python to use? if I look for a python bin path in the environment variables I find nothing.

env | grep -i python
  • 8
    oh i think i figured it out- it just searches your $PATH for 'python'
    – tMC
    May 6, 2011 at 13:50
  • I've wondered about that too. And why /usr/bin/env? as opposed to /bin/env or env, if it is just getting a list of paths from env? May 6, 2011 at 15:50
  • Just 'env' won't work because it has to be full path. The 'env' program is usually found in /user/bin/env. On some distros it may also be found as /bin/env, but it's safer to go with /usr/bin/env.
    – rettops
    May 7, 2011 at 17:21

3 Answers 3


The shebang line (from “sharp bang”, i.e. #!) is processed by the kernel. The kernel doesn't want to know about environment variables such as PATH. So the name on the shebang line must be an absolute path to an executable. You can also specify an additional argument to pass to that executable before the script name (with system-dependent restrictions I won't go into here). For example, for a Python script, you can specify


on the first line, and when you execute the script, the kernel will in fact execute /usr/bin/python /path/to/script. But that's not convenient: you need to specify the full path of the command. What if you have python in /usr/bin on some machines and /usr/local/bin on others? Or you want to set your PATH to /home/joe/opt/python-2.5/bin so as to use a specific version of Python? Since the kernel won't do the PATH lookup for you, the idea is to make the kernel run a command that in turns looks up the desired interpreter in the PATH:

#!/fixed/path/to/path-lookup-command python

That path-lookup-command must take the name of an executable as an argument and look it up in PATH and execute it: the kernel will run /fixed/path/to/path-lookup-command python /path/to/script. As it happens, the env command does just that. Its main purpose is to run a command with a different environment, but since it looks up the command name in $PATH, it's perfect for our purpose here.

Although this is not officially guaranteed, historic Unix systems provided env in /usr/bin, and modern systems have kept that location precisely because of the widespread use of #!/usr/bin/env. So, in practice, the way to specify that a script must be executed by the user's favorite Python interpreter is

#!/usr/bin/env python
  • 2
    which one is preferred between env and which? since which will also get the most eligible executable from my PATH environment. Jan 21, 2012 at 19:22
  • 11
    @NikhilMulley which finds the executable and prints its path. env finds the program specified by the first argument and executes it, passing it the remaining arguments.
    – Kevin
    Feb 2, 2012 at 4:54
  • 4
    so is it that env is an eval version of which essentially. Feb 2, 2012 at 5:26
  • 2
    Does which python always yield equal results to #!/usr/bin/env python ? It appears the answer is no. In that case, my question is: how can we programmatically determine what will be executed by any particular shebang?
    – luckman212
    Aug 28, 2022 at 0:09
  • 1

The shebang expects a full path to the interpreter to use so the following syntax would be incorrect:


Setting a full path like this might work:


but would be non portable as python might be installed in /bin, /opt/python/bin, or wherever other location.

Using env

#!/usr/bin/env python

is a method allowing a portable way to specify to the OS a full path equivalent to the one where python is first located in the PATH.


Right, so run:

env | grep PATH

Your $PATH is a list of directories. Unix will go through that list of directories, in order, until it finds "python".

You can see which directory it finds with the 'which' command:

which python
  • Interestingly, I'm seeing a difference in the python sys.path between an activated env $ env python3 (['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/.local/lib/python3.4/site-packages', '/usr/lib/python3.4/site-packages', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']) and ./env/bin/python3 (['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/test/env3/lib/python3.4/site-packages']). Jan 6, 2017 at 0:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .