5 min read

uv - pip killer or yet another package manager?

uv - pip killer or yet another package manager?

Pip has been the go to package manager for Python since time immemorial. But there’s a new kid on the block - uv. So is it worth the try or yet another tool?    

Pip Shortcomings

Pip is a package management system written in Python and is used to install and manage software packages. Even though it is the most used it is one of the slowest package-management system for python, so much that coming across ‘Pip install is slow’ threads is not a rare occurrence. Also one big potential disadvantage with pip is that developers may introduce dependency smells if dependency configuration files are not well written and maintained properly. These dependency smells can lead to severe consequences and negatively impact project maintenance. Another disadvantage is that Pip may not accurately match Python code and can result in a low success rate of inference when restoring a runtime environment.

This blog is by Shivam, an eager engineer, who makes magic and memes happen. If you like this post, try KushoAI today, and start shipping bug-free code faster!

What is uv?

uv is the "pip but blazingly fast™️ because it's written in rust" and is developed by the same folks that built ruff. It is designed as a drop-in replacement for pip and pip-tools for package management. uv supports everything you'd expect from a modern Python packaging tool: editable installs, Git dependencies, URL dependencies, local dependencies, constraint files, source distributions, custom indexes, and more, all designed around drop-in compatibility with your existing tools. uv's virtual environments are standards-compliant and work interchangeably with other tools — there's no lock-in or customization required. It supports Linux, Windows, and macOS, and has been tested at-scale against the public PyPI index.

Why you should give uv a try?

  • A drop-in compatible API, uv's initial release is centered on supporting the pip and pip-tools APIs behind our uv pip interface, making it usable by existing projects with zero configuration. Similarly, uv can be used as "just" a resolver (uv pip compile to lock your dependencies), "just" a virtual environment creator (uv venv), "just" a package installer (uv pip sync), and so on. It's both unified and modular.
  • Focus on performance, uv is 8-10x faster than pip and pip-tools without caching, and 80-115x faster when running with a warm cache (e.g., recreating a virtual environment or updating a dependency). uv uses a global module cache to avoid re-downloading and re-building dependencies, and leverages Copy-on-Write and hardlinks on supported filesystems to minimize disk space usage.
  • Simplified toolchain, uv ships as a single static binary capable of replacing pip, pip-tools, and virtualenv. uv has no direct Python dependency, so you can install it separately from Python itself, avoiding the need to manage pip installations across multiple Python versions (e.g., pip vs. pip3 vs. pip3.7).
  • Dependencies. uv supports alternate resolution strategies, By default, uv follows the standard Python dependency resolution strategy of preferring the latest compatible version of each package. But by passing --resolution=lowest, library authors can test their packages against the lowest-compatible version of their dependencies. uv allows for resolutions against arbitrary target Python versions. While pip and pip-tools always resolve against the currently-installed Python version (generating, e.g., a Python 3.12-compatible resolution when running under Python 3.12), uv accepts a --python-version parameter, enabling you to generate, e.g., Python 3.7-compatible resolutions even when running under newer versions. uv allows for dependency “overrides”. uv takes pip's “constraints” concepts a step further via overrides (-o overrides.txt), which allow the user to guide the resolver by overriding the declared dependencies of a package. Overrides give the user an escape hatch for working around erroneous upper bounds and other incorrectly-declared dependencies.

uv speed comparison

image.png

Resolving (left) and installing (right) the Trio dependencies with a warm cache, to simulate recreating a virtual environment or adding a dependency to an existing project (source).

image.png

Resolving (left) and installing (right) the Trio dependencies with a cold cache, to simulate execution from a clean environment (source).tldr: uv is 8-10x faster than pip and pip-tools without caching, and 80-115x faster when running with a warm cache (e.g., recreating a virtual environment or updating a dependency).

image.png

Creating a virtual environment, with (left) and without (right) seed packages like pip and setuptools (source).tldr: uv is about 80x faster than python -m venv and 7x faster than virtualenv, with no dependency on Python.

How to setup uv for your project

Install uv with their standalone installers, or from PyPI:

# On macOS and Linux.
curl -LsSf https://astral.sh/uv/install.sh | sh

# On Windows.
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# For a specific version.
curl -LsSf https://astral.sh/uv/0.2.11/install.sh | sh
powershell -c "irm https://astral.sh/uv/0.2.11/install.ps1 | iex"

# With pip.
pip install uv
# come on guys you use edge to install chrome, so this is fine 

# With pipx.
pipx install uv

# With Homebrew.
brew install uv

To create a virtual environment:

uv venv  # Create a virtual environment at .venv.

To activate the virtual environment:

# On macOS and Linux.
source .venv/bin/activate

# On Windows.
.venv\Scripts\activate

To install a package into the virtual environment:

uv pip install flask                # Install Flask.
uv pip install -r requirements.txt  # Install from a requirements.txt file.
uv pip install -e .                 # Install the current project in editable mode.
uv pip install "package @ ."        # Install the current project from disk.
uv pip install "flask[dotenv]"      # Install Flask with "dotenv" extra.

To generate a set of locked dependencies:

uv pip compile requirements.in -o requirements.txt    # Read a requirements.in file.
uv pip compile pyproject.toml -o requirements.txt     # Read a pyproject.toml file.
uv pip compile setup.py -o requirements.txt           # Read a setup.py file.
echo flask | uv pip compile - -o requirements.txt     # Read from stdin.
uv pip freeze | uv pip compile - -o requirements.txt  # Lock the current environment.

To sync a set of locked dependencies with the virtual environment:

uv pip sync requirements.txt  # Install from a requirements.txt file.

uv's pip-install and pip-compile commands support many of the same command-line arguments as existing tools, including -r requirements.txt, -c constraints.txt, -e . (for editable installs), --index-url, and more.

Not all is sunshine and rainbows on uv side

While uv supports a large subset of the pip interface, it does not support the entire feature set. In some cases, those differences are intentional; in others, they're a result of uv's early stage of development.

  • While uv supports a large fraction of the pip interface, it lacks support for some of its legacy features, like .egg distributions.
  • It generates a platform-specific requirements.txt file (unlike, e.g., poetry and pdm, which generate platform-agnostic poetry.lock and pdm.lock files). As such, uv's requirements.txt files may not be portable across platforms and Python versions.

At KushoAI, we're building an AI agent that tests your APIs for you. Bring in API information in any format and watch KushoAI turn it into fully functional and exhaustive test suites in minutes.