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:
[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"Recommended Solution: Using migrate-to-uv
Step-by-Step Migration
- Install migration tools:
pipx install uv
uv pip install uv-migrate- Run the migration command:
cd your-project-directory
uvx migrate-to-uv- Generate the lock file:
uv lock- Install dependencies:
uv syncKey Changes Performed by migrate-to-uv
| Original Poetry Section | Converted UV Section |
|---|---|
[tool.poetry.dependencies] | [project.dependencies] |
[tool.poetry.group.dev] | [dependency-groups.dev] |
| Poetry-compatible version spec | PEP 621-compatible requirements |
poetry.lock file | Removed & replaced with uv.lock |
Handling Private Repositories
For projects using private package repositories:
# 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-uvAlternatively include directly in pyproject.toml:
[[tool.uv.index]]
name = "custom-repo"
url = "https://your-private-repo.example.com/simple/"Post-Migration Verification
- Verify authors format conversion:
# Before
authors = ["John Doe <john.doe@company.com>"]
# After
authors = [
{name = "John Doe", email = "john.doe@company.com"}
]- Confirm build-system update:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"- Run test suite to verify dependencies:
uv run pytestAlternative Approach: Manual Conversion
- Convert with PDM:
uvx pdm import pyproject.toml- Modify dependency groups:
# Replace
[tool.pdm.dev-dependencies]
# With
[dependency-groups]- Remove all Poetry-specific sections:
# 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:
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:
bashuv lock --refresh uv pip list --outdatedMissing 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
| Task | Poetry Command | UV Equivalent |
|---|---|---|
| Add dependency | poetry add package | uv add package |
| Install dependencies | poetry install | uv sync |
| Remove dependency | poetry remove pkg | uv remove pkg |
| Update dependencies | poetry update | uv update |
| Generate lockfile | poetry lock | uv lock |
| Virtual environment | poetry shell | source .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.