JF's Dev Blog

Django, Vue, and other things, too

Pipenv and Poetry: Benchmarks & Ergonomics II

Pipenv and Poetry

Welcome!

I started working on Pipenv and Poetry: Benchmarks & Ergonomics at the begining of 2019, so it seemed only fitting that I provide an update before 2020–'here near the year rear', if you will.

In that time, Python has become the 2nd most popular language on GitHub, and Blog posts about Python dependency management continue to prompt lengthy disucssions online.

Python dependency management is a hot topic even in the tiny corner of the Internet that is this blog. My first Pipenv vs Poetry comparison is my most popular post by ~27%, and two of my three top posts relate to Poetry. And it's no wonder. There are so many ways to manage Python packages and versions that it's hard to keep them straight.

There's the classic pip + Virtualenv setup, recommended by the likes of Django. pip, you say? Not to be confused with pipx, which installs Python applications in isolated environments. Virtualenv, you say? Don't confuse that for virtualenvwrapper, which provides helpful wrapper comands around Virtualenv.

Oh, and about Virtualenv: it's been partly integrated into the Python standard library as venv.

Looking for different versions of Python to put into those virtual environments? There's a tool for that, too: pyenv.

In the scientific computing and machine learning part of the Python galaxy, Conda and its little ssssssissssster Miniconda are all the rage, but they aren't just Python package managers because they manage system dependencies and packages for other languages, too.

Whew! With that embarassment of riches, it's no wonder people are still looking for guidance on how to manage Python packages in 2019.

But enough about those eight (!) tools for managing Python versions and their packages. Let's take a look at how Pipenv and Poetry stack up after eight months of development, first at their current versions, then ergonomic enhancements, and finally benchmarks.

Eight months of releases (?)

In my last post on this subject, I referred to Pipenv and Poetry as "maturing next-generation Python dependency management tools".

This time around, while Poetry has had nearly a page of releases toward its v1.0.0, Pipenv has been waiting on a new release since November 26, 2018.

Poor Pipenv.

While Poetry has seen meaningful usability improvements in the past eight months, any improvements in Pipenv's >660 commits since its last release have yet to make it to users.

This post compares the latest Pipenv and Poetry versions–and in Pipenv's case, 'late' might be a triple entendre.

Feature Pipenv Poetry
Version compared 2018.11.26 1.0.0b5

Ergonomic Enhancements

Installing dependencies

As of Poetry v1.0.0a3, it's possible to disable Poetry's default behaviour of installing the local project as a dependency using:

poetry install --no-root

The benchmarks that follow will include this flag for a truer comparison of Poetry and Pipenv install speeds.

Since my last post, Poetry has also gained the ability to skip installing dev dependencies using the --no-dev flag.

For Pipenv and Poetry, these commands are functionally equivalent:

pipenv install --dev

poetry install --no-root

Poetry shell

As of v1.0.0b2, The Poetry shell no longer exists on Ctrl+C when using fish.

This is thanks to changing how Poetry was launching a shell to how Pipenv does.

Benchmarks

These benchmarks are meant to compare the relative speed of common commands used during development. Each of the commands is benchmarked using time, running on my AMD Ryzen 5 1600.

For this round of benchmarking, I increased the number of dependencies to mirror a Django REST Framework project with good development tooling. This should yield benchmarking figures more in line with what you'd see in a real project.

Dependencies Dev Dependencies
django black
django-redis bpython
djangorestframework django-debug-toolbar
pendulum factory_boy
psycopg2-binary flake8
redis flake8-mypy
mypy
pytest
pytest-watch

Benchmark results

The output of each command is pretty well unchanged since my last post on this topic, so I've excluded that this time around.

The faster command is indicated in bold.

Task Poetry Pipenv
Full install (without lockfile) 70.93s 38.42s
Full install (with lockfile) 62.35s 22.75s
Add dependency:
flake8-markdown
3.55s 19.99s
Lock dependencies 3.49s 11.15s
Remove dependency 2.97s 13.93s

Not much has changed since last time. Pipenv is still faster for full installs, which makes for speedier CI/CD. Poetry is still faster for everything else, making it feel snappier during development.

Wrap-up

Here's my wrap-up from last time:

Poetry's version 1.0 is set to address the two areas where I preferred Pipenv: being able to export a requirements.txt file, and being able to avoid installing a package as a dependency of itself.

If Poetry keeps it up, once version 1.0 is released, I can see myself reaching for it in every new project I start.

Until that point, Pipenv could speed up, remove orphaned dependencies on uninstall, and win me back.

Wouldn't that be romantic?

Well, Poetry has kept it up, and it delivered every feature on my wishlist. With the ergonomic improvements since my last comparison, Poetry has become my tool of choice for any new projects, whether they're applications or packages.

That isn't to say that everyone should move on from Pipenv. This blog still uses Pipenv because it does the trick and I haven't had enough of a reason to change to Poetry to bother. Plus, the Python Heroku buildpack still doesn't support Poetry, so Pipenv may still be a better fit for anyone with a buildpack-based deployment (e.g., Heroku, Dokku, CapRover).

To the majority of most users, however, I recommend Poetry for its active development and broader applicability as both a dependency manager and package manager.

In short: Pipenv vs Poetry? Pick Poetry.