Virtualenv Tutorial

by Szymon LipiƄski

Here is a newer version of this virtualenv tutorial.

What Virtualenv Is

Virtualenv is a great piece of software. It allows to create virtual environments. Each of them can have a different version of Python and different sets of libraries.

While creating this tutorial I used following tools and versions:

Do I Need a Virtual Environment?

As usually: it depends. Normally you can create and use Python programs without that, but using virtual environments can help a lot.

Such a virtual environment provides many possibilities such as:

Basic Steps with Virtualenv

Installation

Installation is very easy. The best way is to perform a system wide installation so all users can create, and use the virtualenv. This must be done from an administrator account. I use Ubuntu on my laptop and I will use the sudo command, on other systems that could be done some other way.

The command for installing is simple:

    sudo easy_install virtualenv

A successful command execution should print on the console something like this:

    sudo easy_install virtualenv
    Searching for virtualenv
    Best match: virtualenv 1.4.8
    Processing virtualenv-1.4.8-py2.6.egg
    Adding virtualenv 1.4.8 to easy-install.pth file
    Installing virtualenv script to /usr/local/bin

    Using /usr/local/lib/python2.6/dist-packages/virtualenv-1.4.8-py2.6.egg
    Processing dependencies for virtualenv
    Finished processing dependencies for virtualenv

Creating the First Virtual Environment

Creating the virtual environment is very easy. First of all choose the directory where you want to create it. The best location would be your home directory.

Let’s create there a special directory where all different environments will be placed. The directory will be named virt_env. For creating this directory I’ll use the normal mkdir command:

    mkdir virt_env

Now let’s create the first virtual environment inside this directory. Normally that’s done using the command:

    virtualenv virt_env/virt1

but first let’s talk a bit about the most useful parameters that we can pass there.

Possible Parameters for Virtualenv
How to Create The Virtual Environment for Python

I will change now the command shown earlier by adding some parameters. I don’t want to use any preinstalled packages from my operating system, so the command looks like this:

    virtualenv virt_env/virt1 --no-site-packages

Output for the command should be like this:

    New python executable in virt_env/virt1/bin/python
    Installing setuptools............done.

Output using the --verbose parameter is a little bit messy, so don’t use it normally. This is useful only to debug some internals when you want to know how it works or when it doesn’t work:

    virtualenv virt_env/virt1 --no-site-packages --verbose

    Creating virt_env/virt1/lib/python2.6
    Symlinking Python bootstrap modules
      Symlinking virt_env/virt1/lib/python2.6/re.pyc
      Symlinking virt_env/virt1/lib/python2.6/codecs.pyc
      Symlinking virt_env/virt1/lib/python2.6/posixpath.pyo
      Symlinking virt_env/virt1/lib/python2.6/re.py
      Symlinking virt_env/virt1/lib/python2.6/stat.py
      Symlinking virt_env/virt1/lib/python2.6/UserDict.pyc
      Symlinking virt_env/virt1/lib/python2.6/posixpath.pyc
      Symlinking virt_env/virt1/lib/python2.6/re.pyo
      Symlinking virt_env/virt1/lib/python2.6/sre_constants.pyo
      Symlinking virt_env/virt1/lib/python2.6/sre.pyc
      Symlinking virt_env/virt1/lib/python2.6/sre_constants.py
      Symlinking virt_env/virt1/lib/python2.6/genericpath.pyc
      Symlinking virt_env/virt1/lib/python2.6/sre_compile.pyo
      Symlinking virt_env/virt1/lib/python2.6/posixpath.py
      Symlinking virt_env/virt1/lib/python2.6/lib-dynload
      Symlinking virt_env/virt1/lib/python2.6/copy_reg.pyc
      Symlinking virt_env/virt1/lib/python2.6/codecs.py
      Symlinking virt_env/virt1/lib/python2.6/copy_reg.py
      Symlinking virt_env/virt1/lib/python2.6/genericpath.pyo
      Symlinking virt_env/virt1/lib/python2.6/abc.pyo
      Symlinking virt_env/virt1/lib/python2.6/warnings.pyo
      Symlinking virt_env/virt1/lib/python2.6/stat.pyc
      Symlinking virt_env/virt1/lib/python2.6/sre_parse.py
      Symlinking virt_env/virt1/lib/python2.6/fnmatch.py
      Symlinking virt_env/virt1/lib/python2.6/fnmatch.pyc
      Symlinking virt_env/virt1/lib/python2.6/_abcoll.pyc
      Symlinking virt_env/virt1/lib/python2.6/os.py
      Symlinking virt_env/virt1/lib/python2.6/os.pyo
      Symlinking virt_env/virt1/lib/python2.6/encodings
      Symlinking virt_env/virt1/lib/python2.6/warnings.py
      Symlinking virt_env/virt1/lib/python2.6/UserDict.pyo
      Symlinking virt_env/virt1/lib/python2.6/abc.pyc
      Symlinking virt_env/virt1/lib/python2.6/locale.pyc
      Symlinking virt_env/virt1/lib/python2.6/sre_parse.pyc
      Symlinking virt_env/virt1/lib/python2.6/_abcoll.py
      Symlinking virt_env/virt1/lib/python2.6/types.pyo
      Symlinking virt_env/virt1/lib/python2.6/config
      Symlinking virt_env/virt1/lib/python2.6/codecs.pyo
      Symlinking virt_env/virt1/lib/python2.6/stat.pyo
      Symlinking virt_env/virt1/lib/python2.6/locale.pyo
      Symlinking virt_env/virt1/lib/python2.6/ntpath.pyc
      Symlinking virt_env/virt1/lib/python2.6/copy_reg.pyo
      Symlinking virt_env/virt1/lib/python2.6/sre_constants.pyc
      Symlinking virt_env/virt1/lib/python2.6/genericpath.py
      Symlinking virt_env/virt1/lib/python2.6/types.py
      Symlinking virt_env/virt1/lib/python2.6/sre_compile.pyc
      Symlinking virt_env/virt1/lib/python2.6/ntpath.py
      Symlinking virt_env/virt1/lib/python2.6/os.pyc
      Symlinking virt_env/virt1/lib/python2.6/_abcoll.pyo
      Symlinking virt_env/virt1/lib/python2.6/sre_compile.py
      Symlinking virt_env/virt1/lib/python2.6/fnmatch.pyo
      Symlinking virt_env/virt1/lib/python2.6/linecache.pyc
      Symlinking virt_env/virt1/lib/python2.6/types.pyc
      Symlinking virt_env/virt1/lib/python2.6/sre.py
      Symlinking virt_env/virt1/lib/python2.6/abc.py
      Symlinking virt_env/virt1/lib/python2.6/warnings.pyc
      Symlinking virt_env/virt1/lib/python2.6/UserDict.py
      Symlinking virt_env/virt1/lib/python2.6/sre_parse.pyo
      Symlinking virt_env/virt1/lib/python2.6/linecache.pyo
      Symlinking virt_env/virt1/lib/python2.6/linecache.py
      Symlinking virt_env/virt1/lib/python2.6/locale.py
    Creating virt_env/virt1/lib/python2.6/site-packages
    Writing virt_env/virt1/lib/python2.6/site.py
    Writing virt_env/virt1/lib/python2.6/orig-prefix.txt
    Writing virt_env/virt1/lib/python2.6/no-global-site-packages.txt
    Creating parent directories for virt_env/virt1/include
    Symlinking virt_env/virt1/include/python2.6
    Creating virt_env/virt1/bin
    New python executable in virt_env/virt1/bin/python
    Changed mode of virt_env/virt1/bin/python to 0755
    Testing executable with virt_env/virt1/bin/python -c "import sys; print sys.prefix"
    Got sys.prefix result: '/home/virt/virt_env/virt1'
    Creating virt_env/virt1/lib/python2.6/distutils
    Writing virt_env/virt1/lib/python2.6/distutils/__init__.py
    Writing virt_env/virt1/lib/python2.6/distutils/distutils.cfg
    Using existing setuptools egg: /usr/local/lib/python2.6/dist-packages/virtualenv-1.4.8-py2.6.egg/virtualenv_support/setuptools-0.6c11-py2.6.egg
    Installing setuptools..........
      Processing dependencies for setuptools==0.6c11
      Finished processing dependencies for setuptools==0.6c11
    ...Installing setuptools...done.
    Installing pip-0.7.1.tar.gz
      Processing pip-0.7.1.tar.gz
      Running pip-0.7.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-xgmRQJ/pip-0.7.1/egg-dist-tmp-N5lGfG
      warning: no previously-included files matching '*.txt' found under directory 'docs/_build'
      no previously-included directories found matching 'docs/_build/_sources'
      zip_safe flag not set; analyzing archive contents...
      pip.venv: module references __file__
      pip.basecommand: module references __file__
      pip.runner: module references __file__
      pip.vcs.__init__: module references __file__
      Adding pip 0.7.1 to easy-install.pth file
      Processing dependencies for pip==0.7.1
      Finished processing dependencies for pip==0.7.1
    Writing virt_env/virt1/bin/activate
    Writing virt_env/virt1/bin/activate_this.py

Using the Virtual Python Environment

Activating the Environment

Using the virtual environment is pretty simple. First of all you have to define what environment you want to use. So far there is just one environment but later will be more.

Let’s use this one environment. The environment directory is

    virt_env/virt1/

the command for loading this environment is:

    virt@ymon:~$ source virt_env/virt1/bin/activate

A successful execution changes the prompt, now it looks like this:

    (virt1)virt@ymon:~$

The first part of the prompt is the name of the virtual environment so it is very easy to see which environment is currently used. Of course you can change the prompt to the previous version but I wouldn’t recommend that as it can become very messy when using more environments.

Deactivating The Current Environment

Current environment can be easily deactivated using command

    (virt1)virt@ymon:~$ deactivate

that reverts the prompt to previous version and now it looks like this:

    virt@ymon:~$

The deactivate command exists only when a virtual environment is active, so don’t be surprised that there isn’t any when you outside the environment.

Installing Packages in Environment

Checking What is Installed

For listing all installed Python packages I will use yolk. This is a simple console program which can list installed packages.

Installation is quite simple:

    sudo easy_install yolk

Usage is even simpler:

    yolk -l

Running that command outside the virtual environment shows me just 114 packages so I will not paste the whole list here.

Using the yolk in the new environment needs installing that locally, so let’s install:

    virt@ymon:~$ source virt_env/virt1/bin/activate
    (virt1)virt@ymon:~$ easy_install yolk
    Searching for yolk
    Best match: yolk 0.4.1
    Processing yolk-0.4.1-py2.6.egg
    yolk 0.4.1 is already the active version in easy-install.pth
    Installing yolk script to /home/virt/virt_env/virt1/bin

    Using /home/virt/virt_env/virt1/lib/python2.6/site-packages/yolk-0.4.1-py2.6.egg
    Processing dependencies for yolk
    Finished processing dependencies for yolk
    (virt1)virt@ymon:~$

Now I can use that locally. On the new virtual environment there isn’t much packages:

    (virt1)virt@ymon:~$ yolk -l
    Python          - 2.6.5        - active development (/usr/lib/python2.6/lib-dynload)
    pip             - 0.7.1        - active
    setuptools      - 0.6c11       - active
    wsgiref         - 0.1.2        - active development (/usr/lib/python2.6)
    yolk            - 0.4.1        - active

Installing Other Packages

Now I can install all packages normally, just in the one environment. It will not touch any other packages from other environments, and even the ones globally packages.

Now I will install Pylons in the environment, but first let’s create other one to ensure that the packages are really installed just in this one.

    (virt1)virt@ymon:~$ deactivate
    virt@ymon:~$ virtualenv virt_env/virt2 --no-site-packages
    New python executable in virt_env/virt2/bin/python
    Installing setuptools............done.

OK, now there is another environment, let’s check what packages are installed there (of course after installing yolk like in the previous one):

    (virt2)virt@ymon:~$ yolk -l
    Python          - 2.6.5        - active development (/usr/lib/python2.6/lib-dynload)
    pip             - 0.7.1        - active
    setuptools      - 0.6c11       - active
    wsgiref         - 0.1.2        - active development (/usr/lib/python2.6)
    yolk            - 0.4.1        - active

Great, the list looks exactly like the previous one.

Now I just switch to the first environment and install Pylons.

    (virt2)virt@ymon:~$ deactivate
    virt@ymon:~$ source virt_env/virt1/bin/activate
    (virt1)virt@ymon:~$ easy_install Pylons

This command prints a lot in the console as it installs many other packages needed by Pylons. The last lines of the messages list look like this:

    Installed /home/virt/virt_env/virt1/lib/python2.6/site-packages/Pygments-1.3.1-py2.6.egg
    Finished processing dependencies for Pylons
    (virt1)virt@ymon:~$

And also let’s install SQLAlchemy library:

    (virt1)virt@ymon:~$ easy_install SqlAlchemy

And now let’s check the list of installed packages:

    (virt1)virt@ymon:~$ yolk -l
    Beaker          - 1.5.3        - active
    FormEncode      - 1.2.2        - active
    Mako            - 0.3.2        - active
    Paste           - 1.7.3.1      - active
    PasteDeploy     - 1.3.3        - active
    PasteScript     - 1.7.3        - active
    Pygments        - 1.3.1        - active
    Pylons          - 0.10rc1      - active
    Python          - 2.6.5        - active development (/usr/lib/python2.6/lib-dynload)
    Routes          - 1.12.1       - active
    SQLAlchemy      - 0.6.0        - active
    Tempita         - 0.4          - active
    WebError        - 0.10.2       - active
    WebHelpers      - 1.0b6        - active
    WebOb           - 0.9.8        - active
    WebTest         - 1.2.1        - active
    decorator       - 3.1.2        - active
    nose            - 0.11.3       - active
    pip             - 0.7.1        - active
    setuptools      - 0.6c11       - active
    simplejson      - 2.1.1        - active
    wsgiref         - 0.1.2        - active development (/usr/lib/python2.6)
    yolk            - 0.4.1        - active

As you can see there is installed the version 0.6.0 of SQLAlchemy library.

Great, it just works but what about the second environment? Does it have those packages also installed?

    (virt1)virt@ymon:~$ deactivate
    virt@ymon:~$ source virt_env/virt2/bin/activate
    (virt2)virt@ymon:~$ yolk -l
    Python          - 2.6.5        - active development (/usr/lib/python2.6/lib-dynload)
    pip             - 0.7.1        - active
    setuptools      - 0.6c11       - active
    wsgiref         - 0.1.2        - active development (/usr/lib/python2.6)
    yolk            - 0.4.1        - active

It seems that everything is OK, so let’s install there Pylons and check the list of installed packages:

    (virt1)virt@ymon:~$ deactivate
    virt@ymon:~$ source virt_env/virt2/bin/activate
    (virt2)virt@ymon:~$ easy_install Pylons
    [... here a lot of messages ...]
    Processing dependencies for Pylons
    Finished processing dependencies for Pylons
    (virt2)virt@ymon:~$ yolk -l
    Beaker          - 1.5.3        - active
    FormEncode      - 1.2.2        - active
    Mako            - 0.3.2        - active
    Paste           - 1.7.3.1      - active
    PasteDeploy     - 1.3.3        - active
    PasteScript     - 1.7.3        - active
    Pygments        - 1.3.1        - active
    Pylons          - 0.10rc1      - active
    Python          - 2.6.5        - active development (/usr/lib/python2.6/lib-dynload)
    Routes          - 1.12.1       - active
    Tempita         - 0.4          - active
    WebError        - 0.10.2       - active
    WebHelpers      - 1.0b6        - active
    WebOb           - 0.9.8        - active
    WebTest         - 1.2.1        - active
    decorator       - 3.1.2        - active
    nose            - 0.11.3       - active
    pip             - 0.7.1        - active
    setuptools      - 0.6c11       - active
    simplejson      - 2.1.1        - active
    wsgiref         - 0.1.2        - active development (/usr/lib/python2.6)
    yolk            - 0.4.1        - active

Great, but there is no SQLAlchemy. So let’s install that but using the previous version, that means installing the version 0.5.0.

    (virt2)virt@ymon:~$ easy_install "SQLAlchemy==0.5.0"
    Searching for SQLAlchemy==0.5.0
    Reading http://pypi.python.org/simple/SQLAlchemy/
    Reading http://www.sqlalchemy.org
    Best match: SQLAlchemy 0.5.0
    Downloading http://pypi.python.org/packages/source/S/SQLAlchemy/SQLAlchemy-0.5.0.tar.gz##md5=df49f403b2db3c54aace64aebe26cf90
    Processing SQLAlchemy-0.5.0.tar.gz
    Running SQLAlchemy-0.5.0/setup.py -q bdist_egg --dist-dir /tmp/easy_install-T1eI2f/SQLAlchemy-0.5.0/egg-dist-tmp-jnaNHq
    no previously-included directories found matching 'doc/build/output'
    zip_safe flag not set; analyzing archive contents...
    sqlalchemy.databases.mysql: module MAY be using inspect.stack
    Adding SQLAlchemy 0.5.0 to easy-install.pth file

    Installed /home/virt/virt_env/virt2/lib/python2.6/site-packages/SQLAlchemy-0.5.0-py2.6.egg
    Processing dependencies for SQLAlchemy==0.5.0
    Finished processing dependencies for SQLAlchemy==0.5.0

Looks fine, lets check the installed version:

    (virt2)virt@ymon:~$ yolk -l | grep SQLAlchemy
    SQLAlchemy      - 0.5.0        - active

The Summary

Now I’ve got two Python environments in directories:

    virt_env/virt1/
    virt_env/virt2/

in both there is a different version of Pylons installed.

    In the first there is SQLAlchemy 0.6.0
    In the second there is SQLAlchemy 0.5.0.

Now that’s easy to test the behaviour of the same Pylons application on both versions of SQLAlchemy without any changes in configuration.

Here is a newer version of this virtualenv tutorial.