Table of Contents

What is a virtual environment

A virtual environment is a separate, isolated Python environment from your main system one. The purpose of a virtualenv is extremely simple: create and easily maintain a self contained collection of dependencies/versions specific to a single project/purpose, without polluting or conflicting with the system or other projects dependencies/python versions. Making an habit out of using virtualenv will make developing with Python extremely easier and less painful.


virtualenv is a PyPi package easily installed by running pip install virtualenv, it supports both 2.7 and 3.x version. Its use is very straightforward and can always be recalled by passing the -h (or –help) flag.

Creating a virtualenv

virtualenv venv will create a directory, in our current path, called venv containing the bedrock of our virtual environments. We will now see what this directory contains, starting from how do we activate and thus use such virtual environment.


├── bin
│   ├── activate
│   ├── activate.csh
│   ├──
│   ├── easy_install
│   ├── easy_install-3.6
│   ├── pip
│   ├── pip3
│   ├── pip3.6
│   ├── python -> python3.6
│   ├── python3 -> python3.6
├── include
├── lib
│   └── python3.6
│       └── site-packages
└── pip-selfcheck.json

A simplified tree view of the virtualenv directory structure

The structure itself is pretty simple, it mimics the one presents in the global installation.

  • bin –> files interacting with the virtualenv
  • include –> C headers used during Python packages’ compilation
  • lib –> copy of the installed Python version, it contains a site-packages folder where all the dependencies will be installed.

To activate a virtualenv simply type source path/to/venv/bin/activate (or path/to/venv/Scripts/activate if you are working on Windows)

As you can see the activation script tells our shell to change the directory where it searches for Python

# Before the command
$ which python
/usr/bin/python  (Note that this may varies depending on your system)

# After activating the virtual environment.
$ which python

From now to when you will either close the shell or exit the virtual environment, all your python related actions will take place inside this safe space without polluting or referring your global installation.

Once created a virtualenv is completely empty except for pip and the basic tools required to build packages. You can start plugging in all the dependencies you want, they will be installed inside site-packages as in your normal Python environment.

Once you are done working you can simply exit the virtualenv by deactivating it via deactivate


Some people may find the use of the virtualenv package too cumbersome, for those people virtualenvwrapper comes to the rescue. This wrapper is a rather complex set of shell commands that automates and makes it easier to work with virtual environments, the wrapper provides an intuitive interface to the underlying virtualenv while maintaining all its powerful capabilities (we will see this in action later on when we talk about creating a virtualenv with a specific Python version)

Installation and Configuration

While the script can be easily installed via pip install virtualenvwrapper, it requires a little bit of configuration to get going.

First of all you may want to define the WORKON_HOME that best suits your needs, this will be the directory in which virtualenvwrapper is going to store the various virtual environments you will create, I usually set it to be /home/$USER/Envs. You could recreate the same capabilities with virtualenv alone but it would be pretty pointless.

Then you will have to follow the instructions presented here.

IMPORTANT: the path to the script can vary depending upon the operating system. I ran Arch Linux and usually have to source the file from /usr/bin/

Installing on Windows

While I personally never tried this route the documentation gives plenty of options.

Managing the environments

As stated earlier, virtualenvwrapper makes managing virtual environments extremely intuitive, as with virtualenv when in doubt you can always use the –help flag to find your way around or reference the detailed documentation, setting this considerations aside here are the most commons commands you will be using:

  • mkvirtualenv venv creates a virtual environment named venv in your WORKON_HOME and will automatically source it so you can start working with it right away.
  • workon venv activates the venv virtual environment, you will use this command when you want to start working on an already present virtualenv.
  • rmvirtualenv venv delete the venv virtual environment.
  • lsvirtualenv list all the virtual environments.

Once again, when you have want to exit a virtualenv use the deactivate command.

Creating a virtualenv with a specific Python Interpreter

Creating a virtual environment with a specific Python interpreter is extremely simple. By default when you call virtualenv (or mkvirtualenv with virtualenvwrapper) it will reference the default python executable for said environment. For all Linux based systems, except the ones running Arch, the default python in the global environment points to the Python 2 interpreter. In order to instantiate a virtualenv with a specific Python you could try one of the following.

# Assuming you have virtualenv installed on both Python 2 and Python 3
python2 -m virtualenv venv
python3.6 -m virtualenv venv

# Alternatively
# virtualenv venv --python=PYTHON_INTERPRETER
virtualenv venv --python=python3.6

Workflow differences and final remarks

You should probably default to virtualenvwrapper for all your virtualenv needs, when doing this you should always have a sensible naming scheme for all your virtual environment, personally I use the same name I give to my project (if I am working on a project called good_skynet I will give the same name to the related virtual environment mkvirtualenv good_skynet) as to easily remember it when calling the workon command.

While virtualenv and virtualenvwrapper are excellent for someone starting out, they are just a stepping stone towards more advanced concepts (which I will soon cover)

  • pip-tools + pipreqs or A sane workflow for dependencies’ management/pinning
  • conda: a package manager that comes with the Miniconda or Anaconda Python distributions (Python distributions geared toward the scientific community). While similar to pip it offers more advanced features, among which the creation and management of virtual environments, requiring a proper primer.
  • pipenv this is a new tool, from our savior Kenneth Reitz, which combines virtualenv, pip, Pipfile and the logic of the aforementioned workflow into one simple package. This could very well be the be-all and the end-all dependencies’ management tool.