When managing a Python project, there comes a time to keep Python packages separated from your main environment. There may be incompatible versions that clobber each other, and you can get into potentially bizarre indeterministic behavior.
To avoid these things, you need to create segregated environments, and historically, virtualenv has been just the tool to do this in the Python universe.
You need Python obviously. If you have python already, skip ahead.
The one question is which Python, which Python? Both Pythons?
- Python 2
- Python 3
I’ll leave that up to you, as this guide should work with both.
The pyenv Option
The best way in my experience, is to use a pyenv to install either or exact
python3 python versions. This is an easy way to control the exact python version on *nix systems like macOS, FreeBSD, and Linux.
If you are content with using the python installed with package managers, you can use them instead.
You can install a local python for your current user with Homebrew:
brew install python@2
You can use Chocolatey to install Python:
choco install python2
Linux: Ubuntu 16.04
Ubuntu already comes with Python. You can use this to both Python versions, Python 2 and Python 3 environments on Ubuntu.
# upgrade latest pythons
sudo apt-get update
sudo apt-get -y upgrade# install pip package manager (required)
sudo apt-get install -y python-pip python3-pip# install compilers/libraries (required for some packages)
sudo apt-get install -y \
The tool virtualenv runs on both Python2 and Python3.
pip install virtualenv
Now we can create a new python virtual environment:
mkdir -p ~/.virtualenvs
Activate the virtual environment, and install a package like flask.
pip install flask
We can see the packages installed with
Deactivate the environment:
After leaving the virtual environment, you can see that packages in our main environment are quite different, as you can see with
There are some convenience tools virtualenvwrapper that offers a more intuitive user experience. Install and setup with the following:
pip install virtualenvwrapper# setup workon area
mkdir -p ~/.virtualenvs
export WORKON_HOME=~/.virtualenvs# add wrapper functions
For Windows users, you can virtualenvwrapper-powershell.
Before we begin, we can look at current packages with
Now install something, like Ansible:
pip install ansible
We’ll have more packages now, as can be seen with pip list:
To leave the environment altogether, run:
Selecting Python Version
If you have multiple Python versions on your system, and would like to use a particular version of Python for your virtualenv, you can do this with the
--python=/path/to/python option with either
Here’s an example using Ubuntu 16.04 environment that has both
python3 executables in the
# example of python2 project (virtualenv)
virtualenv --python=$(which python2) ~/.virtualenvs/site1
pip install django==1.8# example of python3 project (virtualenvwrappers)
mkvirtualenv --python=$(which python2) site2
pip install django==2.1.3
Automatic VirtualEnv with DirEnv
For installation, on macOS, we can use
brew insdtall direnv and on Ubuntu 16.04, we can do
sudo apt-get install direnv . Other operating systems should have some similar procedure. See https://direnv.net/.
We can setup and configure DirEnv for a python environment with this (in bash):
cat <<-'DIRENV_CONFIG' > ~/.direnvrc
DIRENV_CONFIGeval "$(direnv hook bash)"
Note the above instructions are for the bash shell. If you need support for another shell see, https://direnv.net/.
The Python integration notes are from:
Now that we have DirEnv setup, let’s create some environment, using virtualenvwrappers as we did before.
source ~/.local/bin/virtualenvwrapper.sh# create virtualenv
Now we can create a new project, git clone a new repo, etc. and install some local project only packages.
mkdir -p myweb && cd myweb
echo 'layout virtualenv $HOME/.virtualenvs/deployprojs' > .envrc
pip install fabric
If we do a
pip list | grep fabric, we get:
For the first time, we’ll have to manually do a
deactivate, but afterward, activating the project and deactivating the environment only involves switching into the project directory, such as the
myweb example project.
So save the packages in a package manifests for future use on another machine, we can run:
pip freeze > requirements.txt
This will capture our packages for future use in a
requirements.txt file. On a new system, we can switch to the appropriate
virtualenv, and then install the packages again:
pip install -r requirements.txt
This may seem complex, because, well, it is. The takeaways from this are:
- segregating both python platform and package versions
- freezing (saving) python package versions per project
- automating all of this using DirEnv
I documented these, as these have been around for a while and work consistently across both Python 2 and Python 3. Even with new solutions that might be better, you’ll likely come across virtualenv both professionally and in open source projects, so familiarity with this is important.