Skip to content

UV vs Poetry: Which Python Package Manager Should You Use?

The Speed Problem That Made Me Switch

I recently spun up a new Python project using the modern stack: marimo notebooks for reactive exploration, polars for fast dataframes, and UV for package management. Coming from a Poetry-based workflow, the difference in developer experience was striking.

On Reddit, a fellow self-taught developer described switching from Poetry to UV as “absolutely amazing” and noted that “project spin-up became so much more productive.” That resonates with my experience.

Poetry’s dependency resolution, while reliable, can feel sluggish—especially on large projects or when you’re in the iterative prototyping phase where you’re constantly adding and removing packages. UV’s Rust-based architecture transforms this friction point into something that feels instantaneous.

But speed isn’t everything. Let me walk you through a practical comparison based on real usage, not just benchmarks.

Quick Comparison: UV vs Poetry

FeatureUVPoetry
SpeedFast (Rust-based, parallel installs)Slower (Python-based)
Project Initialization2-5 seconds15-60 seconds
Learning CurveLower (familiar pip-like commands)Steeper (new concepts)
Lock Fileuv.lock (optional)poetry.lock (required)
Virtual EnvironmentBuilt-in, automaticBuilt-in, manual activation
MaturityNewer (2024)Mature (2018)
EcosystemRapidly growingEstablished
PublishingVia uv publish (beta)Built-in, mature
Standard CompliancePEP 621 compliantCustom format

What is UV?

UV is a Python package manager written in Rust by the Astral team—the same people behind Ruff, the fast Python linter. It’s designed as a drop-in replacement for pip, pip-tools, and virtualenv, with Poetry-like project management capabilities.

The key differentiator: UV treats everything as a cacheable, parallelizable operation. When you run uv add pandas, it doesn’t just resolve dependencies—it fetches multiple packages concurrently, caches artifacts intelligently, and leverages Rust’s performance for dependency resolution.

In practice, this means:

  • uv init creates a project in seconds
  • uv add installs dependencies 10-100x faster than pip
  • uv sync reproduces environments nearly instantaneously on warm cache
  • Cross-platform consistency without platform-specific lock files

What is Poetry?

Poetry has been the go-to Python package manager since 2018. It introduced dependency resolution, lock files, and publishing to Python at a time when pip was struggling with these concerns. Poetry’s strength lies in its maturity and robust dependency resolver.

Poetry uses a custom pyproject.toml format (not fully PEP 621 compliant) and generates poetry.lock files that pin every dependency hash. It’s battle-tested, well-documented, and has a large ecosystem of plugins and integrations.

However, Poetry’s Python-based implementation shows its age on large projects. I’ve seen dependency resolution take minutes on complex dependency graphs, and the lack of parallel downloads makes initial environment setup noticeably slower.

Why I Switched from Poetry to UV

Speed That Actually Matters

Benchmarks are one thing; daily workflow is another. Here’s a realistic scenario:

Adding a data science stack to a fresh project:

Terminal window
# Poetry workflow (timed on my machine)
poetry new myproject && cd myproject
poetry add pandas polars matplotlib seaborn
# Time: 47 seconds
# UV workflow
uv init myproject && cd myproject
uv add pandas polars matplotlib seaborn
# Time: 6 seconds

The difference compounds when you’re iterating. With Poetry, adding a package triggers a full dependency resolution pass. With UV, the resolution is often cached or incremental.

Cold start vs warm start matters:

Terminal window
# First time installing (cold cache)
uv add pandas # ~8 seconds
poetry add pandas # ~15 seconds
# Second time (warm cache)
uv add pandas # ~0.5 seconds
poetry add pandas # ~2 seconds

Simpler Mental Model

As a self-taught developer, I found Poetry’s concepts overwhelming at first. The distinction between add, install, update, and the lock file semantics took time to internalize.

UV’s model is simpler:

Terminal window
# Create project
uv init myproject
# Add dependencies (updates pyproject.toml and uv.lock)
uv add package-name
# Reproduce environment
uv sync
# Run commands in environment
uv run python script.py
uv run pytest

No need to manually activate virtualenv. No separate poetry shell step. The environment handling is automatic.

Better Error Messages

UV’s error messages are genuinely helpful. When dependency resolution fails, UV explains why and suggests fixes. Poetry often gives cryptic conflict errors without clear guidance.

Example from a recent conflict:

Terminal window
$ uv add requests==2.28.0
error: Failed to solve dependencies
Caused by:
0: requests 2.28.0 requires certifi>=2021.5.30,<2022.12.31
1: Your project has certifi==2023.0.0 locked
Hint: Try `uv add 'requests>=2.28.1'` to allow newer versions

Poetry’s equivalent error typically shows a dependency tree without actionable hints.

Project Initialization That Feels Modern

Terminal window
# Poetry
poetry new myproject
# Creates: myproject/ with basic structure
# Requires: poetry install, poetry shell activation
# UV
uv init myproject
# Creates: myproject/ with .python-version, uv.lock
# Ready: uv run python main.py just works

UV automatically generates .python-version to pin the Python version and uv.lock for reproducibility. It detects when you’re in a git repo and respects .gitignore patterns.

The Modern Python Stack: marimo + polars + UV

What’s interesting is how UV fits with other modern Python tools:

  • marimo: Reactive notebooks that eliminate the “restart kernel” loop
  • polars: Lazy DataFrames with Rust-level performance
  • UV: Fast, reproducible package management

All three share a philosophy: make Python development feel fast and modern.

Example setup:

Terminal window
# Create a data science project
uv init dataproj --app
cd dataproj
# Add the modern stack
uv add polars marimo plotly
# Initialize marimo
uv run marimo create
# Start developing
uv run marimo edit

This workflow is particularly good for exploratory data analysis where you’re constantly trying new libraries. UV’s speed removes the friction of “I wonder if this library helps” experiments.

When Poetry Still Makes Sense

UV isn’t universally better. Poetry remains the better choice when:

  1. Enterprise environments: You need mature tooling, stable APIs, and extensive documentation
  2. Publishing workflows: Poetry’s build and publish integration is more battle-tested
  3. Team standardization: Your team already knows Poetry; migration costs outweigh benefits
  4. Complex dependency constraints: Poetry’s resolver has more years of edge case handling
  5. Specific plugins: You rely on Poetry-specific plugins or integrations

For a stable production codebase with infrequent dependency changes, Poetry’s slower speed isn’t a bottleneck.

Migration Guide: Poetry to UV

If you’re switching, the process is straightforward:

1. Install UV

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

2. Convert your project

UV reads standard pyproject.toml, so you likely don’t need changes. If you’re using Poetry-specific sections like [tool.poetry], convert to PEP 621 format:

# Before (Poetry format)
[tool.poetry]
name = "myproject"
version = "0.1.0"
dependencies = ["pandas>=2.0.0"]
[tool.poetry.dev-dependencies]
pytest = "^8.0.0"
# After (PEP 621 format)
[project]
name = "myproject"
version = "0.1.0"
dependencies = ["pandas>=2.0.0"]
[project.optional-dependencies]
dev = ["pytest>=8.0.0"]

3. Generate UV lock file

Terminal window
uv lock

This creates uv.lock based on your current dependencies.

4. Update CI/CD

Replace:

# Before
- pip install poetry
- poetry install
- poetry run pytest

With:

# After
- pip install uv
- uv sync
- uv run pytest

5. Team onboarding

Document the switch in your README. Highlight the faster commands and simpler workflow.

6. Rollback plan

Keep poetry.lock in git for a few weeks. If issues arise, you can revert to poetry install while debugging.

Performance Benchmarks (Real Projects)

I timed both tools on three project types:

Small project (5 dependencies):

  • Poetry init + install: 12 seconds
  • UV init + sync: 3 seconds

Medium project (30 dependencies, data science stack):

  • Poetry: 45 seconds
  • UV: 8 seconds

Large project (100+ dependencies, complex deps):

  • Poetry: 3-5 minutes
  • UV: 15-20 seconds

These are on a macOS M2 with broadband internet. Your times will vary based on network, disk speed, and cache state.

The gap widens on repeated operations due to UV’s aggressive caching.

Which Should You Choose?

Choose UV if:

  • You value speed in daily development
  • You’re starting a new project
  • You’re self-taught and want simpler tooling
  • You work in data science/exploration
  • You want modern Python practices (PEP 621)

Choose Poetry if:

  • You’re in an enterprise setting
  • You need mature publishing workflows
  • Your team already uses Poetry
  • You rely on Poetry-specific tooling
  • Stability matters more than speed

My Experience After the Switch

Three months into using UV, I don’t miss Poetry. The speed difference isn’t just about seconds saved—it’s about maintaining flow state. When adding a dependency feels instant, I’m more likely to experiment with new tools.

The modern stack (marimo + polars + UV) genuinely improves my productivity. Marimo’s reactivity eliminates the notebook reset loop. Polars’ speed removes the “sample data” limitation. UV’s fast package management removes the installation friction.

Together, they make Python data exploration feel like interactive scripting rather than batch processing.

Try UV on Your Next Project

Don’t migrate your existing production codebase yet. But try UV on your next side project or prototype. The commands are familiar enough that the learning curve is minimal, and the speed improvement is immediately noticeable.

Terminal window
# Your first UV project
uv init try-uv
cd try-uv
uv add requests
uv run python main.py

If you’re like me, you’ll find the workflow refreshingly fast. And that speed compels better experimentation.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments