Skip to content
~/bermudev/blog
Go back

Poetry and uv as modern alternatives to pip

Table of contents

Open Table of contents

Introduction

For many years, pip has been the go-to tool to manage dependencies in Python, and it is still working just fine, but as long as you are working in some backend, microservices or big enough projects, you know that pip can be a little underperforming.

That’s why today I want to show some alternatives that me and my team have been working with in addition to pip, let’s talk about Poetry, uv, and how they compare to pip.


The baseline: pip + venv

This is the classic stack:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

This is simple, explicit, and just works. But not without some limitations:

And the one that worries me the most and took more time for me and my team to fix it:

Dependency confusion in pip

This problem appears when we have private dependencies (for example in an internal registry or private index) that do not exist on PyPI under the same name.

If someone publishes a package on PyPI with that exact name, pip may install the public package first instead of the private one, depending on how index-url and extra-index-url are configured.

For example, imagine our company has an internal package:

company-utils

If that package name does not exist on PyPI and someone publishes a package with that name there, pip could resolve the dependency from PyPI instead of our internal registry.

This issue became widely known a few years ago through several dependency confusion attacks affecting large companies.

In practice, common mitigations include:

It’s not something we run into every day, but when working with internal packages, it’s definitely one of those things you need to consider.

Poetry: packaging and all-in-one dependency management

Poetry arrived with a very clear proposal: unify dependency management, lockfiles, and packaging in one modern tool centered around pyproject.toml.

Instead of working with requirements.txt, setup.py, and other extra files, Poetry tries to give us a single and more coherent workflow.

What it does well

Example:

poetry init
poetry add fastapi
poetry add pytest --group dev
poetry install

In more structured backend projects, this gives us more order and predictability.

What does not fully convince us

In my experience, Poetry is ideal when we are developing a library or we want something formal and reproducible. Or just when we care a lot about project structure.

That said, for day-to-day backend services, sometimes Poetry can feel a bit heavier than what we actually need.

uv: speed and modern pragmatism

uv, developed by Astral (the same people behind Ruff), is written in Rust and has the goal to be extremely fast and compatible with the existing ecosystem.

And when I say fast, I really mean fast.

uv speed comparison chart

What we like about uv

Simple example:

uv venv
uv pip install fastapi

Or even:

uv pip install -r requirements.txt

Without radically changing our workflow.

A quick comparison

So, if I had to summarize it very simply, I would put it like this:

Which one would I choose?

For me, the answer usually looks like this:


Share this post on:

Next Post
Celery: Python's Distributed Task Queue