Virtual environments in Python

8 min. read

Caution! This article is 6 years old. It may be obsolete or show old techniques. It may also still be relevant, and you may find it useful! So it has been marked as deprecated, just in case.

While working in your Python app, you may need to install packages to add extra functionality. Those packages may come in different versions.

To deal with package installation, Python has a tool that works like gem in Ruby, npm in node, etc. It's called pip.

To deal with package versions, Python has another tool which is equivalent to bundler in Ruby, the package.json file in node, etc. It's called virtualenv.

To install pip:

sudo python

To install virtualenv:

sudo pip install virtualenv

The first step when working on a Python app is to create a local environment to install things. Be aware that some files will need execution permissions. In the directory of our future app, type:

virtualenv venv
. venv/bin/activate
(venv) $

This will create a directory venv where everything our app needs will be installed. We also have to activate it, which gives us a special prompt ((venv) $) to let us know that we are in a parallel universe where our packages "exist".

To install your app packages in its environment, for example, if you wanted to install the requests package:

(venv) pip install requests
(venv) pip freeze # will print all installed packages and their versions.

When we are finished working on our app we can deactivate the environment to recover our normal prompt (going back to our universe), or close that terminal window.

(venv) deactivate venv

Say hi to virtualenvwrapper: virtualenv on steroids

There is a wrapper around virtualenv called virtualenvwrapper, that offers more functionality. You can learn more about it in its official website.

To install: First check if you have it installed:

dpkg -l | grep virtualenvwrapper

Then install it:

sudo apt-get install virtualenvwrapper

Then you have to do some set up:

# add it to your .bashrc file too
export VIRTUALENVWRAPPER_PYTHON=/home/USERNAME/.pyenv/shims/python
export WORKON_HOME=/opt/virtualenvwrapper
mkdir -p $WORKON_HOME

To create an environment:


If you want to create it with a specific version of Python:

mkvirtualenv -a PATH_TO_YOUR_APP --python=/usr/bin/python3.4 YOUR_APP_NAME

This makes a dir for the project inside /home/admin/.virtualenvs. Edit the .project file inside the project's folder to point it to the path where the project lives.

After that, you have these commands available:

  • cdvirtualenv: takes you to the virtualenv directory in your home directory.
  • cdproject: will take you to the path where your project lives.
  • workon YOUR_APP_NAME: will take you to the path AND inside environment of your project.
  • deactivate: will take you out of the environment of your project.

This tool is so cool and convenient that it became the environment tool that I use for everything I do in Python these days.

Other handy tools when working with Python

Flake8 as a linter

I use atom as my editor, and I have used linters for Javascript in the past, so I searched if there was anything like that for Python. There is an official package called linter-flake8 which does live checking following the flake8 style guide. You can also install flake8 as a CLI command, and it has some nice configuration options. For example, I have E221 and E501 in "Ignore Error codes" in the package settings. You can also specify this on the terminal.

Pry-like shell with IPython

IPython is a tool that you can install together with Django as an alternative to the Django shell, and it gives you bash completion, colored output, etc. For example, something that you can do is dir(classname), which is equivalent to cd classname in pry, i.e., a command that allows you to see the guts of a class, its methods, member fields, etc.

Debugging with ipdb

This is the equivalent of throwing a binding.pry in your code in Ruby. Instead of binding.pry, in Python you can type:

import ipdb; ipdb.set_trace()

It looks long, but when I start typing import ipdb in atom on a Python file, it autocompletes the whole command (it also does the same with binding.pry)

Some handy commands to move through the code that I haven't check if pry has as well are:

  • n: next line
  • up: go up in the stack trace
  • down: go down in the stack trace

Better dependency management with pipenv

This Thoughbot post explains it all.

Rake-like task runner

I found three tools:

Automatically keep packages up to date

In Ruby most people use Gemnasium, but there is a service called depfu that checks your Gemfile.lock against gem updates and submits a PR if any gems have released a newer version.

There is a similar service for python. It's called pyup.

Where do I go next?

Next, you may want to go back to my Python cheatsheet or jump to my Django cheatsheet. I hope they are useful!