uv and ruff are creating new ways of working with Python
uv has completely changed the way I think about virtual environments. For many years I have been using conda simply because it is the first type of environment manager I learnt about. It wasn’t perfect: the solver was very slow; it was hard to completely delete an environment and the files were hard to locate. As I had invested such effort into the creation of each virtual environment, I found that I would form an attachment to each of them. I was hesitant to destroy them and start from scratch. They were my babies.
But now with uv, I can create and destroy my environments in a fraction of a second. I can kill an environment just so I can try the same code with a different version of Python. I don’t care about them anymore. This lack of emotion frees me to be more efficient and follow best practices more willingly.
This is also true for ruff, the linter and formatter tool made by the same developers behind uv. I have previously used the black formatter with pre-commit, but the several second delay annoyed me every time I made a commit. So, I decided to try ruff on a large codebase to see if I could change my attitude… Well turns out that quick is an understatement. It was so good that I had to double check to confirm that any files had been changed. Or in other words:
it’s so fast I couldn’t believe it was working till I intentionally introduced some errors
Quick tools don’t just remove painful barriers but they can allow new ways of working to develop. With uv, someone can run a script I send them without needing additional environment.yml
or requirements.txt
files. Borrowing the example from calmcode:
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
This also means you can also treat python packages like command line tools. For example, we can run the cookiecutter package like this:
uvx cookiecutter gh:simonw/click-app
uv will create a new environment so quick that you won’t notice this has happened!