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
| Feature | UV | Poetry |
|---|---|---|
| Speed | Fast (Rust-based, parallel installs) | Slower (Python-based) |
| Project Initialization | 2-5 seconds | 15-60 seconds |
| Learning Curve | Lower (familiar pip-like commands) | Steeper (new concepts) |
| Lock File | uv.lock (optional) | poetry.lock (required) |
| Virtual Environment | Built-in, automatic | Built-in, manual activation |
| Maturity | Newer (2024) | Mature (2018) |
| Ecosystem | Rapidly growing | Established |
| Publishing | Via uv publish (beta) | Built-in, mature |
| Standard Compliance | PEP 621 compliant | Custom 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 initcreates a project in secondsuv addinstalls dependencies 10-100x faster than pipuv syncreproduces 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:
# Poetry workflow (timed on my machine)poetry new myproject && cd myprojectpoetry add pandas polars matplotlib seaborn# Time: 47 seconds
# UV workflowuv init myproject && cd myprojectuv add pandas polars matplotlib seaborn# Time: 6 secondsThe 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:
# First time installing (cold cache)uv add pandas # ~8 secondspoetry add pandas # ~15 seconds
# Second time (warm cache)uv add pandas # ~0.5 secondspoetry add pandas # ~2 secondsSimpler 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:
# Create projectuv init myproject
# Add dependencies (updates pyproject.toml and uv.lock)uv add package-name
# Reproduce environmentuv sync
# Run commands in environmentuv run python script.pyuv run pytestNo 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:
$ uv add requests==2.28.0error: 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 versionsPoetry’s equivalent error typically shows a dependency tree without actionable hints.
Project Initialization That Feels Modern
# Poetrypoetry new myproject# Creates: myproject/ with basic structure# Requires: poetry install, poetry shell activation
# UVuv init myproject# Creates: myproject/ with .python-version, uv.lock# Ready: uv run python main.py just worksUV 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:
# Create a data science projectuv init dataproj --appcd dataproj
# Add the modern stackuv add polars marimo plotly
# Initialize marimouv run marimo create
# Start developinguv run marimo editThis 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:
- Enterprise environments: You need mature tooling, stable APIs, and extensive documentation
- Publishing workflows: Poetry’s build and publish integration is more battle-tested
- Team standardization: Your team already knows Poetry; migration costs outweigh benefits
- Complex dependency constraints: Poetry’s resolver has more years of edge case handling
- 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
curl -LsSf https://astral.sh/uv/install.sh | sh2. 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
uv lockThis creates uv.lock based on your current dependencies.
4. Update CI/CD
Replace:
# Before- pip install poetry- poetry install- poetry run pytestWith:
# After- pip install uv- uv sync- uv run pytest5. 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.
# Your first UV projectuv init try-uvcd try-uvuv add requestsuv run python main.pyIf 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:
- 👨💻 UV Documentation
- 👨💻 Poetry Documentation
- 👨💻 Marimo Notebooks
- 👨💻 Polars DataFrame Library
- 👨💻 Ruff: Fast Python Linter
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments