Automatically load a virtualenv when running a script

There are two ways to do this:

  1. Put the name of the virtual env python into first line of the script. Like this

    #!/your/virtual/env/path/bin/python

  2. Add virtual environment directories to the sys.path. Note that you need to import sys library. Like this

    import sys

    sys.path.append('/path/to/virtual/env/lib')

If you go with the second option you might need to add multiple paths to the sys.path (site etc). The best way to get it is to run your virtual env python interpreter and fish out the sys.path value. Like this:

/your/virtual/env/bin/python

Python blah blah blah

> import sys
> print sys.path
[ 'blah', 'blah' , 'blah' ]

Copy the value of sys.path into the snippet above.


I'm surprised that nobody has mentioned this yet, but this is why there is a file called activate_this.py in the virtualenv's bin directory. You can pass that to execfile() to alter the module search path for the currently running interpreter.

# doing execfile() on this file will alter the current interpreter's
# environment so you can import libraries in the virtualenv
activate_this_file = "/path/to/virtualenv/bin/activate_this.py"

execfile(activate_this_file, dict(__file__=activate_this_file))

You can put this file at the top of your script to force the script to always run in that virtualenv. Unlike the modifying hashbang, you can use relative path with by doing:

script_directory = os.path.dirname(os.path.abspath(__file__))
activate_this_file = os.path.join(script_directory, '../../relative/path/to/env/bin/activate_this.py')

From the virtualenv documentation:

If you directly run a script or the python interpreter from the virtualenv’s bin/ directory (e.g. path/to/env/bin/pip or /path/to/env/bin/python script.py) there’s no need for activation.

So if you just call the python executable in your virtualenv, your virtualenv will be 'active'. So you can create a script like this:

#!/bin/bash

PATH_TO_MY_VENV=/opt/django/ev_scraper/venv/bin

$PATH_TO_MY_VENV/python -c 'import sys; print(sys.version_info)'
python -c 'import sys; print(sys.version_info)'

When I run this script on my system, the two calls to python print what you see below. (Python 3.2.3 is in my virtualenv, and 2.7.3 is my system Python.)

sys.version_info(major=3, minor=2, micro=3, releaselevel='final', serial=0)
sys.version_info(major=2, minor=7, micro=3, releaselevel='final', serial=0)

So any libraries you have installed in your virtualenv will be available when you call $PATH_TO_MY_VENV/python. Calls to your regular system python will of course be unaware of whatever is in the virtualenv.