---
title: How to manage your Python projects with Pipenv
teaser: 'Use Pipenv to simplify the management of dependencies in your Python projects.

  '
tags: python,devtools,web
author: Murtaza Gulamali
published_on: 2017-02-20
---

We are well known for [our work with Ruby and Rails][rb] here at thoughtbot, but
generally we always try to use the most appropriate language or framework for
the problem at hand. With that, I've recently been
exploring [machine learning][ml] techniques so I've been working a lot more
in [Python][py].

One of the big differences between working on Ruby projects and Python projects
is the way that dependencies are typically managed. There currently isn't
anything similar to [Bundler][bundler] or [Gemfiles][gemfiles] in the Python
universe so usually a Python developer will create a virtual environment
using [Virtualenv][venv], and then annotate a `requirements.txt` text file with
a list of dependent packages, which they can then install using [Pip][pip].

This approach works fine but sometimes it can be a juggling act, as you have to
manually install or remove packages with particular versions, and remember to
regularly update the `requirements.txt` file, in order to keep the project
environment consistent. Especially when there are Python packages you want
installed in your virtual environment, but not necessarily associated with the
project itself. Moreover, some projects sometimes maintain two versions of the
`requirements.txt` file -- one for the development environment and one for the
production environment -- which can lead to further complications.

Fortunately [Kenneth Reitz's][reitz] latest tool, [Pipenv][pipenv], serves to
simplify the management of dependencies in Python-based projects. It brings
together [Pip][pip], [Pipfile][pipfile] and [Virtualenv][venv] to provide a
straightforward and powerful command line tool.

## Getting started

Begin by using `pip` to install [Pipenv][pipenv] and its dependencies,

```shell
pip install pipenv
```

Then change directory to the folder containing your Python project and
initiate [Pipenv][pipenv],

```shell
cd my_project
pipenv install
```

This will create two new files, `Pipfile` and `Pipfile.lock`, in your project
directory, and a new virtual environment for your project if it doesn't exist
already. If you add the `--two` or `--three` flags to that last command above,
it will initialise your project to use Python 2 or 3, respectively. Otherwise
the default version of Python will be used.

## Managing Python dependencies

[Pipfiles][pipfile] contain information about the dependencies of your project,
and supercede the `requirements.txt` file that is typically used in Python
projects. If you've initiated [Pipenv][pipenv] in a project with an existing
`requirements.txt` file, you should install all the packages listed in that file
using [Pipenv][pipenv], before removing it from the project.

To install a Python package for your project use the `install` keyword. For
example,

```shell
pipenv install beautifulsoup4
```

will install the current version of the [Beautiful Soup][bs4] package. A package
can be removed in a similar way with the `uninstall` keyword,

```shell
pipenv uninstall beautifulsoup4
```

The package name, together with its version and a list of its own dependencies,
can be frozen by updating the `Pipfile.lock`. This is done using the `lock`
keyword,

```shell
pipenv lock
```

It's worth adding the [Pipfiles][pipfile] to your Git repository, so that if
another user were to clone the repository, all they would have to do is
install [Pipenv][pipenv] on their system and then type,

```shell
pipenv install
```

Then [Pipenv][pipenv] would automagically locate the [Pipfiles][pipfile], create
a new virtual environment and install the necessary packages.

## Managing your development environment

There are usually some Python packages that are only required in your
development environment and not in your production environment, such
as [unit testing packages][testing]. [Pipenv][pipenv] will let you keep the two
environments separate using the `--dev` flag. For example,

```shell
pipenv install --dev nose2
```

will install [nose2], but will also associate it as a package that is only
required in your development environment. This is useful because now, if you
were to install your project in your production environment with,

```shell
pipenv install
```

the [nose2] package won't be installed by default. However, if another developer
were to clone your project into their own development environment, they could
use the `--dev` flag,

```shell
pipenv install --dev
```

and install all the dependencies, including the development packages.

## Running your code

In order to activate the virtual environment associated with your Python project
you can simply use the `shell` keyword,

```shell
pipenv shell
```

You can also invoke shell commands in your virtual environment, without
explicitly activating it first, by using the `run` keyword. For example,

```shell
pipenv run which python
```

will run the `which python` command in your virtual environment, and display the
path where the `python` executable, that is associated with your virtual
environment, is located. This feature is a neat way of running your own Python
code in the virtual environment,

```shell
pipenv run python my_project.py
```

If you're like me and shudder at having to type so much every time you want to
run Python, you can always set up an alias in your shell, such as,

```shell
alias prp="pipenv run python"
```

## Keeping it simple

I hope this post has shown you how to manage your Python projects
with [Pipenv][pipenv]. It has been around for less than a month now, so I, for
one, will be interested to see how it develops over time. I certainly don't
want, or expect, it to become exactly like [Bundler for Ruby][bundler], but I'll
definitely champion it for simplifying the management of dependencies in Python
projects. I hope you do too!

[bs4]: https://www.crummy.com/software/BeautifulSoup/ "Beautiful Soup"
[bundler]: https://bundler.io/ "Bundler"
[gemfiles]: https://bundler.io/gemfile.html "Gemfiles"
[ml]: https://en.wikipedia.org/wiki/Machine_learning "Machine learning"
[nose2]: https://nose2.readthedocs.io/en/latest/ "nose2"
[pip]: https://pip.pypa.io/en/stable/ "Pip"
[pipenv]: http://docs.pipenv.org/ "Pipenv"
[pipfile]: https://github.com/pypa/pipfile "Pipfile"
[py]: https://thoughtbot.com/services/python-django "Python at thoughtbot"
[reitz]: https://www.kennethreitz.org/ "Kenneth Reitz"
[rb]: https://thoughtbot.com/services/ruby-on-rails "Ruby and Rails at thoughtbot"
[testing]: http://docs.python-guide.org/en/latest/writing/tests/ "Testing your code"
[venv]: https://virtualenv.pypa.io/en/stable/ "Virtualenv"
