The importance of env (and how it works with virtualenv)

18 September 2008   8 comments   Python

Powered by Fusion×

I have for a long time wondered why I'm supposed to use this in the top of my executable python files:

#!/usr/bin/env python

Today I figured out why.

The alternative, which you see a lot around is something like this:


Here's why it's better to use env rather than the direct path to the executable: virtualenv. Perhaps there are plenty of other reasons the Linux experts can teach me but this is now my first obvious benefit of doing it the way I'm supposed to do it.

If you create a virtualenv, enter it and activate it so that writing:

$ python 

starts the python executable of the virtual environment, then this will be respected if you use the env shebang header. Good to know.


The main reason why it's a good idea to use the /usr/bin/env approach is that not everyone has python installed in the same place -- sometimes it's in /usr/bin, sometimes it's in /usr/local/bin or /opt/local/bin, sometimes you have to install your own copy in your home directory, etc.

If you use the /usr/bin/env version then it will find the python executable by looking in your path, so all you have to do is update your .profile or other appropriate startup scripts to include the appropriate directory in your path and your scripts will work everywhere without modification.

If you hardcode the path as /usr/bin/python and then move the script to a machine where it is installed in /usr/local/bin (or send the script to someone that has it installed there), you'll have to edit the script to get it to work.

Obviously this is more important if you are distributing your scripts to the public or a large group of people with different environments but it can be helpful even if the scripts are just for you. For example, I have both regular python and stackless python installed on the same machine and I need to run some things in one environment and some in the other, so I have aliases set up that change my path to point to the appropriate interpreter. If I used the hardcoded approach I wouldn't get the right interpreter automatically.
A reason not to use /usr/bin/env is that then the name of the process is not the name of the script. Having the script name as the process name is helpful in looking at process listings and when it is behaving badly and you need to kill it.
Peter Bengtsson
I don't think so. Not in bash (ubuntu).

$ cat | head -1
#!/usr/bin/env python
$ ./ runserver &
$ ps ax | grep env
$ px ax | grep python
25582 pts/8 Sl+ 0:00 /home/peterbe/dev/DJANGO/myapp/bin/python ./ runserver
25654 pts/7 R+ 0:00 grep python
$ head -1 ; ./ & ps axc | grep ; echo done
#!/usr/bin/env python
[1] 14079
$ head -1 ; ./ & ps axc | grep ; echo done
[1] 14086
14086 pts/12 R 0:00
Peter Bengtsson
I see! Thanks!
Christopher Arndt
One caveat with the "#!/usr/bin/env prog" idiom is that it will most likely not work when your script is executed in a limited environment, e.g. as a CGI script by your web server.
virtualenv or any other installation approach that runs Python from a non-system directory, that is.

Python's always been easy to install anywhere you like; it uses heuristics to locate the library based on the location of the library.
Jim Dennis
#!/usr/bin/env as the "shebang" line has been customary with Python for at least a decade and a half. It can also be used with Perl, TCL, Ruby and so on. But that hadn't been the convention for most other scripting languages. (Ruby has also adopted /usr/bin/env, especially for use with its rvm and rbenv (Ruby's analogs to Python's virtualenv.

Your email will never ever be published

Related posts

The stupidity of 'id' as a variable name (or stupidity of me) 16 September 2008
V8 < TraceMonkey < SquirrelFish 23 September 2008
Related by keywords:
COPYFILE_DISABLE and python distutils in python 2.6 12 April 2014
ztar - my wrapper on tar -z 29 June 2005