News & Views

Modern Python Development with uv

Engineering

The modern Python developer ecosystem has evolved considerably over time.

Although the core Python utilities have remained relatively stable (such as pip), there has been significant community development of tools which aim to simplify and/or improve different parts of working with Python.

To name just a few:

  • uvPython package and project manager
  • PoetryPython package and dependency manager
  • pyenvPython version manager
  • HatchPython project manager
  • PDMPython package and dependency manager
  • AnacondaDistribution platform for Python

This is just a small selection of the popular tools, and a more complete list is available at:

 

With numerous tools available, which should you choose? As of 2025, the Python community has fairly unanimously agreed that uv is the leading tool for modern Python development.

Whether you’re an engineer, an analyst, or anything else, you’ll need some way of installing dependencies into your project and managing your files: uv works for everyone, so read on to find out what makes it so awesome.

 

What makes uv the leading Python project manager?

uv is built by Astral, a US software development company focused on building high-performance developer tools for the modern Python ecosystem.

To quote the uv documentation, uv is: An extremely fast Python package and project manager, written in Rust.

uv is an entire project manager because it can:

  • Manage Python installations
  • Manage project files and version
  • Manage virtual environments
  • Manage dependencies
  • Run Python scripts

…in addition to being incredibly fast (see below) and having several quality-of-life features.

Installing Trio’s dependencies with a warm cache (source)

Below we’ll showcase a few reasons why Tasman have switched over to uv, and why it is the leading tool for modern Python development.

 

Effortless uv installation

One of the best things about uv is that it just works.

Installation is easy; it has no non-trivial dependencies and you just run a single CLI command for your environment. uv is available directly, and on several package managers.

Regardless of how you install it, uv will then work immediately:

  • No environment variables to configure
  • No shell hooks to add
  • No dependency conflicts to worry about

Like with the uv commands, the installation is also very fast — and subsequent updates are as simple as:

uv self update

 

Virtual environments by default

How many times have you forgotten to activate a virtual environment?

We’ve all been there: you come back to Python after a taking a break and have to Google how to activate virtual environments again… And hopefully you remember to do this before accidentally installing all your packages globally.

uv defaults to using virtual environments and handles activating and deactivating them for you. No more activate commands needed!

Even better, uv understands Python project build systems so, as long as you’ve made your package installable (which is highly recommended), uv can figure out how to build the virtual environments automatically.

This means that instead of writing:

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
dbt debug
deactivate

…we can simply write:

uv run dbt debug

…and uv will figure out the rest!

✅ Pro tip: if you want uv to use an existing virtual environment, say venv, just set the VIRTUAL_ENV environment variable and use the --active and --no-sync flags:

VIRTUAL_ENV=venv uv run --active --no-sync dbt debug

 

Streamlined Python installation management

The previous example showed that uv can figure out how to create and manage virtual environments automatically when a project is installable. It can also figure out which version of Python to use!

Managing Python installations manually isn’t ideal. Until uv, it was common to use pyenv for this instead.

The CLI commands for managing Python installations in uv is similar to pyenv. For example, to manage Python 3.10, the commands are:

  • uv python install 3.10 to install the latest Python 3.10 distribution*
  • uv python uninstall 3.10 to uninstall the current Python 3.10 installation
  • uv python upgrade 3.10 to upgrade the existing Python 3.10 installation
  • uv python list to list all installed Python versions, and their corresponding executable path

 

ℹ️ *Note that Python does not publish official distributable binaries, so uv uses distributions from the Astral python-build-standalone project.

✅ For more details, check out the corresponding uv docs:

Modern Python dependency declaration

PEP 518 introduced the pyproject.toml configuration file as a better standard for specifying Python project metadata. Numerous tools have been updated to support this file (both reading from it and writing to it), and uv is no exception.

Instead of the usual pip install ... command which only installs a package, uv recommends using the uv add ... command which:

  • Adds the specified project to the dependencies array in the pyproject.toml file
  • Freezes the full project dependencies to a uv.lock file
  • Automatically creates a new virtual environment if one doesn’t exist, otherwise actives the existing one (where the virtual environment is inside a .venv folder, in both cases)
  • Installs the specified package into the virtual environment

The uv.lock file is uv’s way of recording which packages are in the project environment with their exact versions, which is perfect for cross-team development as the same virtual environment can be created with the uv sync command.

Similarly, the dependencies array in the pyproject.toml file just specifies the immediate dependencies with allowed version ranges which is great for libraries so that the project can be installed in a larger environment with different dependency requirements.

If you prefer, you can always specify your dependencies directly in the dependencies array without an existing uv.lock file, and uv sync will install the dependencies in a virtual environment and freeze a new uv.lock file for you!

# pyproject.toml
[project]
name = "my-awesome-project"
version = "0.1.0"
description = "Something awesome."
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "pydantic>=2.11.7",
    "requests>=2.32.4",
]

Easy scripting and dependency specification

We’ve seen that uv run ... can figure out which dependencies to use when used in an installable project.

There are two other ways that you can tell uv which dependencies to include:

For example, suppose we had some Python file, example.py, with the following contents:

import requests

print(requests.get("<https://example.com>").text)

 

This depends on the third-party package Requests. Running this without Requests installed will cause a failure, but we can tell uv to install this package with the --with argument like so:

uv run --with requests example.py

 

Alternatively, we could specify the dependency using the inline script metadata comment (PEP 723):

# /// script
# dependencies = [
#   "requests",
# ]
# ///

import requests

print(requests.get("<https://example.com>").text)

 

…and then running uv run example.py will know to install the Requests dependency.

In both cases, you can also include version specifiers on your dependencies, and declare a Python version too! See the Running scripts guide for more details.

Finally, on a unix platform, you can also add a uv shebang to make a script executable without using uv run (but you’ll still need to add the execute permission on the file with chmod +x or equivalent):

#!/usr/bin/env -S uv run --script

# /// script
# dependencies = [
# "requests",
# ]
# ///

import requests

print(requests.get("<https://example.com>").text

Other uv features we love for modern Python development

There’s too much to go into in just this article, but there’s still so much we love about uv and what it brings to modern Python development.

We’ll briefly run through a few more examples and link appropriate docs for you to explore.

uv’s pip subcommand

uv’s pip subcommand has an API very similar to the Python pip interface, so you can start using uv to manage your existing Python projects without much effort. For example, you can install dependencies from a requirements file with:

uv pip install -r requirements.txt

uv’s tool subcommand

Python package that provide CLIs can be installed as “tools” with uv tool install ... and run with uv tool run ..., or uvx ... for brevity. This keeps the tools isolated in their own environments but free to use across multiple projects.

uv’s version subcommand

uv can read and update the current project’s version with the uv version subcommand — and if you’re following the semantic version spec (SemVer), you can easily bump your project version with uv version --bump and supplying one of the SemVer semantic types, e.g. uv version --bump patch.

uv’s build and publish subcommands

uv can build your package and publish it to an index. For example, building and publishing to PyPI on a Unix machine is as simple as uv build && uv publish, and both subcommands have several options for configuring the process to fit your requirements.

Migrating to uv: simplified

The Astral folk are starting to document how to migrate from other tools to uv:

At the time of writing (2025-09-05), there’s only only article which is for migrating from pip to uv, but additional articles are planned.

There are also community tools for migrating to uv such as the following tool which, at the time of writing, supports migrating from Poetry, Pipenv, pip-tools, and pip:

 

The broader Astral ecosystem: Ruff, ty, and pyx

Astral’s flagship product was actually their linter/formatter, Ruff, and they have subsequently been working on ty, a type checker, and pyx, a package registry.

Like uv, Ruff aims to replace many of the existing linting and formatting tools such as Black, Flake8, and Pylint (among others); as with uv, one of the driving improvements is speed:

Linting the CPython codebase from scratch (source)

Both ty and pyx are in early development, but we expect great things from both of them.

Make uv part of your modern Python ecosystem with Tasman’s expert insights

With Python being the backbone of data, ML, and AI work, the modern Python ecosystem is a rapidly evolving space and its corresponding developer tools are no exception.

Whatever your Python development needs – from data analytics to enterprise applications – switching to uv will likely benefit your workflow. At Tasman Analytics, we’ve already made uv one of our go-to tools for modern Python development.

Interested in exploring how uv could fit into your Python development stack? We’d be happy to share our experiences and discuss how modern Python tools can enhance your projects.