Skip to content

Migrating from Poetry to UV

Problem

Many Python developers using Poetry face challenges when migrating to the newer uv package manager. Common hurdles include:

  • Lack of official migration guides
  • Uncertainty about required modifications in pyproject.toml
  • Confusion around proper build system configuration
  • Concerns about preserving dependency groups and private repository access
  • Potential dependency version conflicts during migration

Below is a typical Poetry pyproject.toml that requires conversion:

ini
[tool.poetry]
name = "name"
version = "1.6.0"
description = ""
# ... poetry configuration

[tool.poetry.dependencies]
python = "^3.12"
fastapi = "^0.115.2"
# ... dependencies

[tool.poetry.group.dev.dependencies]
pytest = "^8.3.3"
# ... dev dependencies

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

Step-by-Step Migration

  1. Install migration tools:
bash
pipx install uv
uv pip install uv-migrate
  1. Run the migration command:
bash
cd your-project-directory
uvx migrate-to-uv
  1. Generate the lock file:
bash
uv lock
  1. Install dependencies:
bash
uv sync

Key Changes Performed by migrate-to-uv

Original Poetry SectionConverted UV Section
[tool.poetry.dependencies][project.dependencies]
[tool.poetry.group.dev][dependency-groups.dev]
Poetry-compatible version specPEP 621-compatible requirements
poetry.lock fileRemoved & replaced with uv.lock

Handling Private Repositories

For projects using private package repositories:

bash
# For source named "company-repo" in tool.poetry.source
export UV_INDEX_COMPANY_REPO_USERNAME=<username>
export UV_INDEX_COMPANY_REPO_PASSWORD=<password>
uvx migrate-to-uv

Alternatively include directly in pyproject.toml:

ini
[[tool.uv.index]]
name = "custom-repo"
url = "https://your-private-repo.example.com/simple/"

Post-Migration Verification

  1. Verify authors format conversion:
ini
# Before
authors = ["John Doe <john.doe@company.com>"]

# After
authors = [
    {name = "John Doe", email = "john.doe@company.com"}
]
  1. Confirm build-system update:
ini
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
  1. Run test suite to verify dependencies:
bash
uv run pytest

Alternative Approach: Manual Conversion

  1. Convert with PDM:
bash
uvx pdm import pyproject.toml
  1. Modify dependency groups:
ini
# Replace
[tool.pdm.dev-dependencies]

# With
[dependency-groups]
  1. Remove all Poetry-specific sections:
ini
# Remove these blocks:
[tool.poetry]
[tool.poetry.dependencies]
[tool.poetry.group.dev]

Preserving Exact Dependency Versions (Optional Advanced Step)

Use this script to enforce Poetry's locked versions during migration:

python
from pathlib import Path
import toml

lock_data = toml.load(Path("poetry.lock"))
pyproject_data = toml.load(Path("pyproject.toml"))

locked_versions = {pkg["name"]: pkg["version"] for pkg in lock_data["package"]}

def update_deps(section):
    for dep in list(section):
        if dep in locked_versions:
            section[dep] = locked_versions[dep]

update_deps(pyproject_data["tool"]["poetry"]["dependencies"])
update_deps(pyproject_data["tool"]["poetry"]["group"]["dev"]["dependencies"])

with open("pyproject.toml", "w") as f:
    toml.dump(pyproject_data, f)

WARNING

Use this script with caution! It may generate invalid constraints for dependencies with special sources or extras. After migration, revert the frozen versions.

Troubleshooting

  • Dependency resolution conflicts:

    bash
    uv lock --refresh
    uv pip list --outdated
  • Missing build backend:

    diff
    + [build-system]
    + requires = ["hatchling"]
    + build-backend = "hatchling.build"
  • Authentication failures: Verify UV_INDEX_* environment variables match your private repository names exactly

TIP

If migrating complex projects, run uv pip freeze > requirements.txt pre-migration to compare dependency versions post-migration

Post-Migration Commands Cheat Sheet

TaskPoetry CommandUV Equivalent
Add dependencypoetry add packageuv add package
Install dependenciespoetry installuv sync
Remove dependencypoetry remove pkguv remove pkg
Update dependenciespoetry updateuv update
Generate lockfilepoetry lockuv lock
Virtual environmentpoetry shellsource .venv/Scripts/activate (Windows/Linux)

By following these steps, you'll maintain dependency consistency while benefiting from UV's improved performance and modern tooling features.