Creating Virtual Python Software Environments With Virtualenv
Creating Virtual Python Software Environments With Virtualenv
Anders Johansen1
1
Center for Biomedical Computing, Simula Research Laboratory
2
Department of Informatics, University of Oslo
0.1 Motivation
The most difficult aspect of installing a particular software package is usually
to get all the dependencies right. That is, the package requires the existence
of a lot of other packages on the computer system. These packages also have
their dependencies. In addition, some packages only work with certain versions
of other packages. Getting dependencies and software versions right quickly
becomes a challenging problem. Even more critical is the fact that installing
a new set of packages brings in other versions of some software that affect the
behavior of previously installed software on the computer system.
To be specific, think of package a that depends on packages b and c in their
respective versions 1.0 and 1.2 or newer. Then we install package d, which also
requires package c, but in an older version 0.6. Package c in v0.6 overwrites
v1.2, causing package a to break.
A good solution to the problem of incompatible dependencies, and in fact a
good solution to handle dependencies in general, is to create an isolated virtual
environment where we can install the packages in the versions we want. We can
have several such isolated environments on our system and none of them interfere
with the global software system. Also, we can easily delete an environment when
it is no longer needed.
The pip tool itself can be installed from pure Python source2 via the standard
sudo python setup.py install command. On Debian systems (including
Ubuntu) one can install pip by sudo apt-get install python-pip.
The virtualenv script creates a new virtual environment in a destination
directory here named venv:
Terminal> virtualenv venv
One can apply the -p flag to specify which Python executable to use as the
python program in the environment:
Terminal> virtualenv -p /usr/bin/python2.6
The next step is to activate the virtual environment. To do this, we source the
activation script from the bin subdirectory of the newly created venv directory:
Terminal> cd venv/
Terminal> source bin/activate
2
Terminal> source bin/activate
(venv)Terminal>
The latter command lists all Python packages installed in the current virtualenv.
At this point, there is nothing more than the essential tools like Python and
pip, and of course yolk itself.
Let us also install the Python web framework Django:
(venv)Terminal> pip install Django
What can be installed by pip install? The above examples have installed
Python packages whose names and details are present in the Python Package
Index (PyPi)3 . One can also install from tarballs as long as the root directory
of the tarball contains a setup.py file to do the installation:
(venv)Terminal> pip install ../some/dir/package.tar.gz
(venv)Terminal> pip install http://some.net/dir/package.tar.gz
Installation directly from the source in a version control system is also possible
(if a setup.py resides in the root directory):
(venv)Terminal> pip install -e \
git+https://github.com/hplgit/odespy.git#egg=odespy
3
0.3 Creating a slightly different environment
Say that we have written an app for Django v1.5.1 and want to check that it is
compatible with an earlier version of Django, e.g., v1.4.1. With Virtualenv this is
very easy. All we need to do is deactivating the current virtual environment and
create a new one where we install Django v1.4.1. Deactivation of an environment
is done by the command deactivate:
(venv)Terminal> deactivate
Terminal>
As always, yolk is our tool to assure that the correct version a software is
installed:
(venv2)Terminal> yolk -l | grep Django
Django - 1.4.1 - active
Now we have two Python environments, venv with Django 1.5.1 and venv2
with Django 1.4.1. This makes it easy to test how the same app behaves
on different versions of Django without making any changes to the system’s
configuration. Just copy the files for the app to a directory in the virtual
environment and run.
If all the above steps in creating the venv2 environment have been followed, the
requirements file should have the following content:
Django==1.4.1
argparse==1.2.1
wsgiref==0.1.2
yolk==0.4.3
4
In case one has also installed a Python package from the repository of a version
control system, the particular commit version (and of course the URL) is recorded
as data for that package.
To replicate exactly the same environment inside another Virtualenv en-
vironment, we create a new environment, say it is called venv3, copy the
requirements.txt file to the venv3 environment, and use pip to install all the
packages and their versions specified in requirements.txt at once:
(venv3)Terminal> pip install -r requirements.txt
A yolk -l command can be used to check the success of the multiple installations.
A word of caution is necessary here. Distributing a requirements.txt
file produced by pip freeze will not always re-create an environment by a
simple pip install -r requirements.txt. For example, the output from pip
freeze may not account for the fact that some packages must be installed before
others. When creating a Python environment for doing scientific computing,
numpy is a package that must be installed before most other packages. Some
packages can be challenging to compile via pip install (ScientificPython is an
example, although manual execution of setup.py runs fine). Also, many Python
scientific computing packages depend on much non-Python software that cannot
be installed by pip. For such complex environments it is recommended to create
a script that performs the manual installation tasks, but it can utilize pip to as
large extent as possible.
With this software in place, we can go on with pip install of Python packages:
Terminal> packages="numpy sympy matplotlib scipy ipython nose"
Terminal> for p in packages; do pip install $p; done
Terminal> pip install -e \
git+https://github.com/hplgit/odespy.git#egg=odespy
Note that pip install is preferred over apt-get install of Debian packages
because pip will usually install a newer version of the package. It also opens up
the possibility for installing the development version directly from the package’s
repository on (e.g.) GitHub.
A pip freeze > requirements.txt results as usual in a list of the packages
in the environment, but this file is not so useful.
5
Warning.
This requirement file cannot be used to recreate the environment. The
reason is that there is no way to impose a certain sequence of the packages
for installation. This is demanded, because numpy must be installed before
scipy, matplotlib, and most other packages for numerical computing.
One must therefore provide a Bash script or Python program for installing
the environment. Virtualenv is still useful for having multiple environments
with different versions of, e.g., numpy and matplotlib, but pip install
via a requirements.txt file is not possible.
A Bash script for installing the environment above may look like
#!/bin/sh
apt="yes | sudo apt-get install"
$apt gcc g++ gfortran
$apt libatlas-base-dev libsuitesparse-dev
$apt tcl8.5-dev tk8.5-dev
$apt subversion mercurial cvs git gitk
$apt libfreetype6-dev libpng-dev
$apt mayavi2 tcl-vtk
$apt libsqlite3-dev
packages="numpy sympy matplotlib scipy ipython nose"
for p in packages; do pip install $p; done
pip install -e git+https://github.com/hplgit/odespy.git#egg=odespy
hpl 1: Should refer to the Vagrant document for how to make a list of
packages and then autogenerate scripts.
References.
• Virtualenv documentation4
• Pip documentation5
4 http://www.virtualenv.org/en/latest/
5 http://guide.python-distribute.org/pip.html