← All posts

Migrating a Real Project from Poetry or Pipenv to uv

Moving a project from Poetry or Pipenv to uv is a common upgrade path once teams see the install speed difference. This guide makes the case for switching, then walks through the migration step by step.

Why Switch to uv

Switching from Poetry or Pipenv to uv improves install speed, simplifies the toolchain, and makes dependency management more reliable at scale. Here's what specifically gets better:

Speed. uv is written in Rust and resolves and installs dependencies in parallel. On real-world projects, uv sync routinely finishes in a fraction of the time poetry install or pipenv install takes, especially on a cold cache. That difference compounds across every CI run, every fresh clone, every Docker build.

One tool instead of several. Poetry and Pipenv each handle dependency management and virtual environments. uv does that too, but also manages Python versions (uv python install) and can replace pyenv. Fewer tools means fewer version mismatches and less onboarding friction for new contributors.

A resolver that keeps up with you. Poetry's resolver can slow down significantly on projects with large or conflicting dependency trees, which discourages routine version bumps. uv's resolver stays fast even as the dependency graph grows, so keeping packages current stops being a chore.

Standards-based configuration. uv reads standard pyproject.toml metadata rather than a tool-specific format, so the project is easier to read for anyone familiar with modern Python packaging, not just Poetry users.

Reliable, reproducible installs. Like Poetry and Pipenv, uv generates a lockfile (uv.lock) with hashes for every dependency. Combined with uv sync --frozen in CI, this closes the gap between "works on my machine" and "works in the pipeline."

Together, these add up to less time spent waiting on installs, fewer moving parts to maintain, and a dependency workflow that scales better as a project grows.

Step 1: Inventory What You Have

Before touching anything, note what your current tool is managing:

  • Dependencies and versions (pyproject.toml for Poetry, Pipfile for Pipenv)
  • A lockfile (poetry.lock or Pipfile.lock)
  • Any custom scripts defined in [tool.poetry.scripts] or Pipenv's [scripts]
  • Python version constraints

Step 2: Install uv

curl -LsSf https://astral.sh/uv/install.sh | sh

Step 3: Convert Your Dependency List

If you're coming from Poetry, your pyproject.toml dependencies mostly transfer as-is since uv also reads standard pyproject.toml format. The main change is the [tool.poetry] section becomes standard [project] metadata:

[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
    "requests>=2.31",
    "fastapi>=0.110",
]

If you're coming from Pipenv, export your Pipfile dependencies into this same [project.dependencies] format manually. There's no automated converter, but for most projects it's a short list to copy over.

Step 4: Generate a Fresh Lockfile

uv lock

This creates a uv.lock file. Don't hand-edit it, treat it the same way you treated poetry.lock.

Step 5: Recreate Your Virtual Environment

uv sync

This reads uv.lock and builds a .venv with exact versions installed. It replaces both poetry install and pipenv install.

Step 6: Update Scripts and CI

Replace commands like:

  • poetry run pytest becomes uv run pytest
  • pipenv run python app.py becomes uv run python app.py

In CI, swap the install step for:

uv sync --frozen

The --frozen flag ensures CI fails loudly if the lockfile is out of sync with pyproject.toml, rather than silently regenerating it.

Step 7: Remove the Old Tooling

Delete poetry.lock or Pipfile/Pipfile.lock, and drop Poetry or Pipenv from your dev dependencies. Double-check that nothing else in the repo (Dockerfiles, Makefiles, pre-commit hooks) still calls the old tool.

What to Expect

On most projects, uv sync on a clean cache completes noticeably faster than poetry install, and CI install steps typically drop too. Just as important, uv's dependency resolver is fast enough that routine dependency bumps stop feeling like a chore, so you're more likely to keep dependencies current.

If your project relies on complex Poetry plugins or Pipenv-specific features, budget extra time to find uv equivalents. For most standard projects, though, this migration is a half-day task, not a rewrite.

Python DevOps uv