Skip to content

How do uv and Poetry compare?

Poetry long served as the default recommendation for Python project management. It brought lockfiles, virtual environments, and pyproject.toml configuration to a packaging ecosystem that needed all three. uv, written in Rust by the team behind Ruff, arrived in 2024 and took on most of Poetry’s responsibilities while adding Python version management and faster dependency resolution. Both tools configure projects through pyproject.toml, create lockfiles, and manage virtual environments. They differ in how.

Scope

Poetry handles dependency management, virtual environments, building, and publishing. Everything else it delegates. A different Python version requires pyenv. Running a CLI tool without installing it globally requires pipx.

uv covers all of that plus Python version management, CLI tool execution (via uvx), and pip-compatible package installation. One binary replaces pyenv, pip, pip-tools, pipx, virtualenv, and Poetry itself. uv takes on more surface area; Poetry stays narrow.

Speed

uv resolves and installs dependencies orders of magnitude faster than Poetry. On a project with a few dozen dependencies, uv sync finishes in under a second; poetry install takes 10-30 seconds. On large projects with hundreds of transitive dependencies, Poetry’s resolver can take minutes. Astral benchmarks uv at 10-100x faster than pip; the gap with Poetry is comparable. uv gets this speed from aggressive caching, a Rust resolver, and parallel downloads.

The gap matters most in CI. A GitHub Actions job using uv finishes faster than the same job using Poetry, and the difference compounds across matrix builds and frequent pushes.

Standards Alignment

Poetry predates several Python packaging standards and used its own metadata format under [tool.poetry]. Poetry 2.0 (January 2025) added support for PEP 621 standard [project] metadata, but many existing projects still use the non-standard format. Poetry also has its own dependency specification syntax; its extras and source declarations differ from PEP 508 specifiers.

uv uses PEP 621 metadata exclusively. Dependencies follow PEP 508. The lockfile format is uv-specific (like Poetry’s poetry.lock), but the project configuration works with any PEP 621-compliant tool. A pyproject.toml from a uv project works with hatch, flit, or pdm without modification. A Poetry project using [tool.poetry.dependencies] requires conversion first.

Lockfiles

Both tools generate lockfiles for reproducible installs. Poetry writes poetry.lock; uv writes uv.lock. Each pins every transitive dependency to an exact version and records hashes.

A single uv.lock captures resolution for Linux, macOS, and Windows. Poetry’s lockfile is also designed to be cross-platform (environment markers are recorded but not evaluated during resolution), though hash coverage may be incomplete for platforms other than the one where poetry lock ran.

Virtual Environment Management

Poetry creates virtual environments in a centralized cache directory (~/.cache/pypoetry/virtualenvs/ on Linux). This keeps the workspace clean but makes the environment harder to find. Poetry can be configured to use an in-project .venv instead.

uv creates a .venv inside the project by default, matching the convention most editors expect. uv run executes commands within the environment automatically. Poetry offers poetry run for the same purpose; for shell activation, Poetry 2.0 replaced poetry shell with poetry env activate.

Python Version Management

Poetry does not manage Python interpreters. It uses whichever Python is on the system and delegates version management to pyenv.

uv installs and manages Python versions directly. uv python install 3.13 downloads a prebuilt binary in seconds. A .python-version file pins the interpreter, and uv run picks it up automatically. No separate version manager, no compilation step.

Dependency Groups

Poetry introduced dependency groups ([tool.poetry.group.dev.dependencies], [tool.poetry.group.test.dependencies]) before any standard existed for them, letting teams separate development, testing, and documentation dependencies.

uv supports PEP 735 dependency groups ([dependency-groups]) and optional dependencies ([project.optional-dependencies]). PEP 735 is a Python standard, so groups defined this way work across any tool that supports it.

Publishing

Poetry has a built-in poetry publish command with support for multiple repositories, token authentication, and certificate configuration.

uv provides uv publish and uv build. For publishing to PyPI from CI, trusted publishing with GitHub Actions is the recommended approach regardless of tool. See the publishing tutorial for a walkthrough.

Plugin Ecosystem

Poetry supports plugins. The poetry-plugin-export plugin (required for poetry export) and community plugins for dynamic versioning, Docker integration, and monorepo support give Poetry extensibility that uv lacks. Teams with custom Poetry plugins should check whether uv covers their use case before migrating.

uv has no plugin system. Features ship in the binary or not at all.

When to Choose Each

Choose uv when:

  • Starting a new project with no existing Poetry configuration
  • Speed in CI and local development matters
  • Managing Python versions without a separate tool is desired
  • Portability of pyproject.toml across build tools matters

Choose Poetry when:

  • An existing project already uses Poetry and migration cost is high
  • The project relies on Poetry plugins with no uv equivalent
  • The team knows Poetry’s workflow and has no reason to switch

Migrating

For teams ready to switch, the handbook has a step-by-step guide: How to migrate from Poetry to uv.

Learn More

Last updated on

Please submit corrections and feedback...