Programming

## uv - One rust tool to rule all pythons

Long story short: I’m now using uv, and so should you. It is a great replacement for pip, pip-tools, pipx, poetry, pyenv, twine, virtualenv, and more.

## Context

For years, my strategy to manage python projects has been a mix of a custom `setup.py`, several hand-crafted `requirements.txt` files (through `pip freeze`), a custom virtualenv per project, and multiple tools to upload to PyPI. Although this works, this setup has many drawbacks:

- It requires user intervention (creating a venv, sourcing it, handling new deps). This isn’t ideal if you want new (probably inexperienced) users to use your projects.
- On a similar note, the whole process needs to be well documented if you want other users to contribute or maintain the code.
- Pinning dependency versions is finicky, and I’ve run into problems beause of that.
- Creating a new project involves a template, or copying files from an older project.

Of course, this is nothing new. There is a whole site dedicated to packaging your Python project. A plethora of different projects have come and go, with varying degrees of success.

## Alternatives (poetry)

About a year before trying `uv`, I tried to catch up with the ecosystem and get to know the `blessed new way`. However, the task proved to be a little more difficult, as the landscape is filled with a myriad of alternatives, each with their own set of drawbacks and detractors. Packaging has historically been a weak spot, in ironical contradiction to the Zen of Python’s “There should be one– and preferably only one –obvious way to do it”,

I eventually settled on poetry. Mostly because it seemed like the most popular alternative.

There are many things I liked about it. First of all, having a convention for dependencies (`pyproject.toml`) and a tool that properly handles them was nice. It also removed the need to remember specific incantations to build and publish my Python projects. Lastly, I mixed it `poetry2nix` to create reproducible python environments using nix. This makes for a very powerful experience.

However, there were multiple hiccups. First of all, it took me some time to figure out which specific fields to use (each tool can define ad-hoc properties in a the `pyproject.toml` file), and some of them seemed redundant with the more generic ones. Full disclosure, this specific point might be a mistake on my side, and I do not remember the details. The second one is speed. (Re-)creating an environment took a non-negligible amount of time.

## Enter light `uv`

According to its repository, `uv` can replace pip, pip-tools, pipx, poetry, pyenv, twine, virtualenv, and more. Not only that, but it also claims to do that 10-100 times faster than pip. I must admit that it being written in rust was a another selling point for me, as I’m looking for excuses to collaborate in a decently-sized rust projejct.

Installing it is dead simple: simply download the binary (e.g., with curl) or run `pip install uv`. You won’t need much more: `uv` seems to just do the right thing out of the box. And it does it really, really fast. The rest of the time it gets out of the way.

My only gripe so far is that I don’t seem to find a built-in command to drop into a shell, but that is nothing that `uv run $SHELL` cannot fix.

## Common operations

### Initialize a repository

    1

    uv init

### Adding dependencies

    1

    uv add senpy

### Running commands inside the environment

    1
    2
    3
    4

    uv run <COMMAND>

    # e.g., run a shell using your python version and dependencies
    uv run $SHELL

### Dependency tree

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    uv shell
    Resolved 44 packages in 1ms
    my-project v0.1.0
    ├── fastapi[standard] v0.115.8
    │   ├── pydantic v2.10.6
    │   │   ├── annotated-types v0.7.0
    │   │   ├── pydantic-core v2.27.2
    │   │   │   └── typing-extensions v4.12.2
    │   │   └── typing-extensions v4.12.2
    │   ├── starlette v0.45.3
    │   │   └── anyio v4.8.0
    │   │       ├── exceptiongroup v1.2.2
    │   │       ├── idna v3.10
    │   │       ├── sniffio v1.3.1
    │   │       └── typing-extensions v4.12.2
    │   ├── typing-extensions v4.12.2
    │   ├── email-validator v2.2.0 (extra: standard)
    │   │   ├── dnspython v2.7.0
    ...

## Related content

## Bridging RDF, JSON-LD and Dataclasses

## Nix Recipe for Python Projects

## Progress bars in python

## Proxies with Apache and python

## Publishing on PyPi