Al Sweigart's Quickstart uv Tutorial
Posted by Al Sweigart in misc
uv (written in lowercase even if it begins a sentence) is a Python package and project manager that has seen rapid popular adoption by the Python community. This is not a full tutorial nor necessarily a good tutorial for you (the uv documentation is great for that) but it's mainly a writing exercise for myself to think about the parts of uv that I use. It's a quickstart, with just the commands I used on my macbook to use it with terse notes that make sense to me. If a sentence exists in this tutorial, it's something I feel I should memorize like a flashcard. As such, it often lacks context or supporting details.
In this document, uv means the uv software and uv means the command.
Install
On macOS, I installed it with Homebrew: brew install uv
The executable gets put in /opt/homebrew/bin/uv
To update uv, run: uv self update
Creating a Project
Like git or brew, uv has several subcommands. Running uv by itself is the same as uv --help.
Creating a new project with uv is similar to git: uv init or uv init my-project. This creates several new files & folders:
- .git
- .gitignore (set up for a basic Python project)
- .python-version (predates uv and used by pyenv, contains just the text
3.13) - main.py ("Hello, world!" stub)
- pyproject.toml (basic settings)
- README.md (blank)
Note that while this creates a git repo, it does not create a .venv virtual environment.
Installing & Managing Python with uv
uv's subcommands have their own "guides" in the uv docs. The uv python subcommand has the Python guide.
uv python install installs Python from Astral's repo and not the official distributable binaries. (These are made from CPython; Astral has not forked Python.)
Running uv python find shows that it installed Python to /Users/al/.local/share/uv/python/cpython-3.13.2-macos-aarch64-none/bin/python3.13 on my machine.
Running uv python list shows that it can install cpython going back to version 3.8 (as of now, March 2026).
I ran uv python install 3.8 to install an old version I hadn't installed anywhere before. It downloaded a 16.6mb file from Astral and installed it in /Users/al/.local/bin/python3.8. (This works outside of all virtual environments and isn't particular to any single project or virtual environment.)
Running Scripts with uv
The running scripts guide docs have more info about using uv to run .py files.
uv run example.py can, effectively, replace python3 example.py. uv handles the details of Python installs, virtual environments, and dependencies. uv run auto-detects pyproject.toml for this info.
Inline script metadata is from PEP 723 and embeds dependency information into the top of a .py file. It's for the case of "I have this single Python script that uses a third-party package like Requests and I just want it to work without telling people to set up the virtual environment and get the right pyproject.toml/requirements.txt file." It's not a publish-ready script, you just want to hand something to a coworker to run real quick.
Inline metadata looks like this:
# /// script
# dependencies = [
# "requests<3",
# "rich",
# ]
# requires-python = ">=3.11"
# ///
Inline metadata comes after the shebang line and can come after the encoding comment.
uv can create a stub script with inline metadata: uv init --script example.py
You can add the info for the "requires-python" and "dependencies" sections too: uv add --script example.py 'requests<3' 'rich'
Note the difference between uv init --script and uv add --script here.
If you aren't in a virtual environment or have one set up, uv run can make it for you: uv run --with rich example.py (or with versions with uv run --with "rich>12,<13" example.py.
uv add --script can add dependencies to the inline metadata section, while uv remove --script removes them. It only affects the .py file's inline metadata section, it doesn't change pyproject.toml or any other files.
uv add and uv remove add/remove dependencies to a project.
Project Management with uv
A "project" in this case means a Python package that has a pyproject.toml file. uv init creates a stub project. uv add and uv remove add/remove dependencies to the pyproject.toml file.
The first time you run uv add to add a dependency to the project, uv also creates the .venv folder and uv.lock file.
NOTE: You can also specify URLs as dependencies, just like pip: uv add git+https://github.com/psf/requests
uv version will display your project's version, as it appears in the pyproject.toml file. Neat little shortcut.
Running Tools with uv
uvx can (like pipx) install and run tools. The most common case is running ruff without having to jump through hoops to install and set it up in a virtual environment. uvx handles that for you.
uvx is a shorthand for uv tool run. It's installed at /opt/homebrew/bin/uvx on my machine.
uvx ruff check example.py will run ruff on example.py.
Conclusion
There's a lot more to uv, but this is the basics. I still recommend learning about the venv package and pip tool in vanilla Python. It's not that complicated and I covered them in my slides for a PyTexas 2025 tutorial. But uv lives up to its hype as a tool that is fast, simple, and convenient.