DEV Community

Cover image for Transition from pip to uv package manager
Nitin Kumar
Nitin Kumar

Posted on

Transition from pip to uv package manager

So, you've already got your traditional pip package manager & transition to uv package manager? Or you're someone who's new to package manager topic?


Python Package Manager

Let's understand what a package manager mean.

A Python package manager is a tool that automates the process of installing, updating, configuring, and removing software packages (libraries) written for Python. Think of it as the software that connects your project to repositories of reusable code, fetches packages (and their dependencies), and manages them on your system or in specific environments.


Choosing uv over traditional pip

Now, let's understand why to choose uv over pip although both are open source !

Metric uv pip
Out-of-the-Box Availability No Yes
Package installation speed Installs JupyterLab in 2.618 seconds Installs JupyterLab in 21.409 seconds
Reproducible installs Supports reproducible installs based on native locking Supports reproducible installs through requirements.txt and pip-tools
Removal of transitive dependencies Yes No
Maturity and ecosystem support Offers a new and growing ecosystem with increasing adoption Offers a mature ecosystem and long-standing adoption
Licensing Distributed under the MIT license Distributed under the MIT license
Supporting organization Developed by Astral, a private company focused on high-performance Python tooling Developed by the Packaging Authority (PyPA), part of the Python Software Foundation (PSF)

You can learn more about their comparison in realpython's blog or this youtube video.


Working of uv package manager

So, it's clear why uv & not pip. But how does uv even works? How is it so fast than pip.

Bootstrapping & Setup

uv is distributed as a single compiled binary and can install Python versions, create virtual environments, and manage dependencies without requiring a pre-configured Python toolchain. Because it is written in Rust, startup time is nearly instant and it works consistently across platforms. In contrast, pip requires Python to already be installed and must be combined with tools like venv or virtualenv, making initial project setup more fragmented and error-prone. In CI environments, reducing setup steps can noticeably decrease build times, especially across multiple pipeline runs.

Dependency Resolution

uv uses a high-performance dependency resolver (inspired by modern solvers like PubGrub) that computes a fully consistent dependency graph before installation begins. This process is deterministic and optimized for speed, especially in large projects. While pip introduced a backtracking resolver in version 20.3, it can still be noticeably slower on complex dependency trees and may require multiple resolution attempts, increasing install time. In large dependency graphs, resolution with pip can take several seconds to minutes depending on conflicts, whereas uv often resolves the same graphs in a fraction of that time due to optimized algorithms.

Lockfile & Reproducibility

uv generates and enforces a native uv.lock file, ensuring reproducible installs across machines and CI pipelines. Every transitive dependency is pinned automatically. pip does not provide built-in lockfile support, relying instead on requirements.txt or external tools like pip-tools, which adds workflow complexity and can reduce determinism. Native locking reduces human error and prevents “works on my machine” problems that frequently arise in pip-based setups without strict version pinning.

Downloading Packages

uv performs parallel downloads and aggressively reuses a global cache, significantly reducing network and installation time. Benchmarks commonly show large projects installing in a fraction of the time compared to traditional tooling (for example, JupyterLab installing in roughly 2–3 seconds in controlled tests). pip typically handles downloads more sequentially and, while it caches packages, it does not optimize parallel fetching to the same extent, making cold installs slower. In some public comparisons, uv demonstrates installation speeds up to 5–10× faster than pip for large dependency sets.

Installation & Disk Efficiency

uv installs packages in parallel and uses hard-linking or symlinking from a shared global cache when possible, reducing redundant disk writes and saving storage across environments. pip installs packages sequentially and copies files into each environment, which can increase disk usage and slow down repeated environment creation in large projects. In multi-environment setups, uv’s deduplicated caching can significantly reduce storage overhead compared to pip’s per-environment duplication model.

Virtual Environment Management

uv integrates virtual environment creation and management directly into its workflow, allowing commands like uv venv and uv sync to streamline setup. pip does not manage environments itself, requiring manual environment activation; mistakes in activation can lead to unintended global package installations and dependency conflicts. Consolidating environment and dependency management in one tool reduces operational friction and configuration mistakes.

Python Version Management

uv can download and manage multiple Python versions as part of its unified toolchain, reducing the need for additional version managers. pip cannot manage Python interpreters, forcing developers to rely on separate tools such as system package managers or pyenv, increasing setup fragmentation. A unified toolchain simplifies onboarding and standardizes development environments across teams.

Performance at Scale

uv is optimized for performance at scale, leveraging parallelism, aggressive caching, and compiled execution. In many real-world benchmarks, it demonstrates multiple-fold speed improvements over traditional workflows, especially in cold installs and CI/CD pipelines. pip, being implemented in Python and not heavily parallelized, can become a bottleneck in large CI/CD pipelines or enterprise-scale dependency graphs, where repeated installs compound time costs across builds.


How to setup

Now, that we know what's uv & how it's faster than pip, let's move to the implementation part.

What are the steps we need to perform to implement uv in our project. Let's begin from scratch. Took help from uv documentation JFYI.

Install uv

macOS / Linux

curl -LsSf https://astral.sh/uv/install.sh | sh
Enter fullscreen mode Exit fullscreen mode

Windows (PowerShell)

irm https://astral.sh/uv/install.ps1 | iex
Enter fullscreen mode Exit fullscreen mode

Or via pip (not recommended for full feature usage, but possible):

pip install uv
Enter fullscreen mode Exit fullscreen mode

; you may use pipx instead of pip for installation in isolated environment.

Verify installation:

uv --version
Enter fullscreen mode Exit fullscreen mode

Create new project

uv init PROJECT_NAME
cd PROJECT_NAME
Enter fullscreen mode Exit fullscreen mode

; PROJECT_NAME is the name of your project

This creates:

  • pyproject.toml
  • .venv (optional depending on config)
  • Basic project structure

Install dependencies

Now, you need to add dependencies/libraries you need to install in your project. You've got 2 options - one with a requirements.txt file where your dependencies are present & another one without anything but you know what all dependencies you need.

If you've got requirements.txt file:

uv add -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

If you don't have that file:

uv add PACKAGE_NAME
Enter fullscreen mode Exit fullscreen mode

then, ensure your environment is in sync with the pyproject.toml and uv.lock files:

uv sync
Enter fullscreen mode Exit fullscreen mode

With this approach, you simply run uv sync when another developer clones the project, and uv automatically creates the virtual environment and installs the correct dependencies. Checkout this YouTube video for reference.


And, that's it !! You're good to use uv as your package manager instead of pip.

If you need to install any other package, just run uv add command & it'll automatically add in current virtual env, updates uv.lock file & add package to .toml file.

No need of requirements.txt file now to install same packages, just put uv sync & all files will be updated based on the shared .toml file.


What exactly happens after we do uv sync:

  • Read uv.lock
  • Create a virtual environment (if not present)
  • Install the exact pinned versions from the lock file
  • Reproduce the same dependency tree deterministically

So yes — everything needed for dependencies gets recreated automatically.

If you still need requirements.txt file to deploy on services not using uv, simply do

uv export -o requirements.txt
Enter fullscreen mode Exit fullscreen mode

So, for sharing dependencies related to your project, just share .toml & .lock files & run uv sync in new system & it'll automatically install all dependencies.


Some errors:

  1. You might get error while updating updating uv (uv self update), for resolution check this github resolution issue comment

  2. You might get error while installing dependencies before doing uv init, this is due to no .toml file. You need to initialize uv project first by doing uv init even if you've project opened. It'll automatically take your project name & initialize with required files & you can install dependencies.


Hope you liked this tutorial on uv implementation in your python project. Let me know in comments how was your experience with uv & how much time is preserved by using it.

!! HAPPY DEVELOPING !! KEEP DEVELOPING !!

If this helped you even a little, feel free to connect with me on 👉 LinkedIn

Top comments (0)