• FAQ
    • Journal
    • Personal ☤ Values
    • Online References
    • Recommendations
    • Tattoos
    • Travel Log
    • ☤ B l a c k b o x ☤
    • BTC & ETH
    • Games
    • ☤ Software for Humans ☤
    • « Podcast »
    • Essays on Development
    • Python-Guide.org (H2G2P)
    • Requests: HTTP for Humans
    • The "Say Thanks" Project.
    • Records: SQL for Humans
    • Maya: Datetimes for Humans
    • Certifi: TLS Trust for Humans
    • Autoenv (Magic CD-ing)
    • em: cli emoji keyboard
    • HTTPbin Testing Service
    • ☤ Conference Talks ☤
    • github.com/kennethreitz
    • ☤ About KR Photography ☤
    • Essays on Photography
    • Flickr (Journal)
    • 500px (portfolio)
    • YouPic (Models)
    • Instagram
  • Sound
  • Video
    • ☤ Conference Talks ☤
    • Scheduled Events
    • Travel Log
    • ☤ All Essays ☤
    • Development
    • Journeys
    • Music
    • Photography
    • Objects
    • ☤ Archives ☤
  • Journal
  • VLOG
Menu

Kenneth Reitz

  • K ☤ R
    • FAQ
    • Journal
    • Personal ☤ Values
    • Online References
    • Recommendations
    • Tattoos
    • Travel Log
    • ☤ B l a c k b o x ☤
    • BTC & ETH
  • Code
    • Games
    • ☤ Software for Humans ☤
    • « Podcast »
    • Essays on Development
    • Python-Guide.org (H2G2P)
    • Requests: HTTP for Humans
    • The "Say Thanks" Project.
    • Records: SQL for Humans
    • Maya: Datetimes for Humans
    • Certifi: TLS Trust for Humans
    • Autoenv (Magic CD-ing)
    • em: cli emoji keyboard
    • HTTPbin Testing Service
    • ☤ Conference Talks ☤
    • github.com/kennethreitz
  • Light
    • ☤ About KR Photography ☤
    • Essays on Photography
    • Flickr (Journal)
    • 500px (portfolio)
    • YouPic (Models)
    • Instagram
  • Sound
  • Video
  • Talks
    • ☤ Conference Talks ☤
    • Scheduled Events
    • Travel Log
  • Essays
    • ☤ All Essays ☤
    • Development
    • Journeys
    • Music
    • Photography
    • Objects
    • ☤ Archives ☤
  • Journal
  • VLOG

Essays by KR — development, music, photography, journeys, objects, & archive.

A Better Pip Workflow™

February 25, 2016

Update: I developed Pipenv to solve these problems. Check it out.


When developing Python applications today, it’s standard practice to have a requirements.txt file in the root of your repository.

This file can be used in different ways, and typically takes one of these two forms:

  1. A list of top-level dependencies a project has, often without versions specified.
  2. A complete list of all dependencies a project has, each with exact versions specified.

Method #1: Simple Requirements

A list of top-level dependencies a a project has, often without versions specified.

$ cat requirements.txt
requests[security]
flask
gunicorn==19.4.5

Method #1 is very simple, and is effectively the user experience that everyone using requirements files wants. However, when a requirements.txt file like this is used to deploy to production, unexpected consequences can occur. Effectively, because versions haven’t been pinned, running $ pip install will give you different results today than it will tomorrow.

This is bad. As different versions of sub-dependencies are released, the result of a fresh $ pip install -r requirements.txt will result in different packages being installed, and potentially, your application failing for unknown and hidden reasons.

Method #2: Exact Requirements

A complete list of all dependencies a project has, each with exact package versions specified.

$ cat requirements.txt
cffi==1.5.2
cryptography==1.2.2
enum34==1.1.2
Flask==0.10.1
gunicorn==19.4.5
idna==2.0
ipaddress==1.0.16
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
ndg-httpsclient==0.4.0
pyasn1==0.1.9
pycparser==2.14
pyOpenSSL==0.15.1
requests==2.9.1
six==1.10.0
Werkzeug==0.11.4

Method #2 is best-practice for deploying applications, and ensures an explicit runtime environment with deterministic builds.

All dependencies, including sub-dependencies, are listed, each with an exact version specified.

This type of requirements.txt is generated from the output of running $ pip freeze from within a current working runtime environment for the application. This encourages dev/prod parity, and encourages you to treat code within external packages with the same level of respect as your application code (because it is your application code).

The Frustrations

While the Method #2 format for requirements.txt is best practice, it is a bit cumbersome. Namely, if I’m working on the codebase, and I want to $ pip install --upgrade some/all of the packages, I am unable to do so easily.

My previous method for doing so was to simply pick out the top-level dependencies with my eyes and manually type out $ pip install requests[security] flask --upgrade. This is not a good experience.

I thought long and hard about building a tool to solve this problem. Others, like pip-tools, already have. But, I don’t want another tool in my toolchain; this should be possible with the tools available.

Eventually, I figured out a nice way to have the best of both worlds in my Python projects, with the tools I already use. I’ve been using this workflow in my projects for a while now, and I’m very happy with the results.

The Workflow

It’s very simple: instead of having one requirements file, you have two:

  • requirements-to-freeze.txt
  • requirements.txt

requirements-to-freeze.txt uses Method #1, and is used to specify your top-level dependencies, and any explicit versions you need to specify.

requirements.txt uses Method #2, and contains the output of $ pip freeze after $ pip install requirements-to-freeze.txt has been run.

Basic Usage

$ cd project-repo

$ pip install -r requirements-to-freeze.txt --upgrade
Installing collected packages: six, enum34, ipaddress, ...

$ pip freeze > requirements.txt

The best of both worlds.

I encourage you to give this workflow a try. There's a good chance that it'll save you from some failing builds and scratching heads in the future :)

In Development
← MentalHealthError: an exception occurred.Introducing Records: SQL for Humans™ →

Recent Posts

Essays
Apple Pencil Note-Taking: Why You Should Use Apple Notes, actually.
about 5 days ago
First Soundtrack Scoring!
about 2 months ago
Logitech CRAFT Keyboard Video Review
about 2 months ago
Leica M10 Video Review
about 2 months ago

Recent Music


Messages to Humans

Receive updates on upcoming projects, new releases, and interesting things from Kenneth Reitz.

Subscribe to Newsletter

Join the Messages for Humans mailing list to receive updates on new releases and upcoming projects. 

 

✨ 🍰 ✨

 

Have a question or comment? Post it in the FAQ Forum.

 

(essays archive, blog rss feed)

External Content. Personal Values. Tattoos. Travel History. Upcoming Events. Archive.