Using uv for Python project management
Reference: 【Doc】【GitHub Repo】
Most of my projects use uv to control the python package and create .venv for better package isolation. Below is a short version of uv guide. Think of it as a long version cheatsheet.
Standalone install
# Through url
$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ wget -qO- https://astral.sh/uv/install.sh | sh
# using pip
$ pip install uv
# self update
$ uv self update
# with pip
$ pip install --upgrade uv
# Uninstall
$ uv cache clean
$ rm -r "$(uv python dir)"
$ rm -r "$(uv tool dir)"
Usage
$ uv init
$ uv add <lib>
$ uv remove <lib>
$ uv run <xx.py>
# Create a lockfile for the project's dependencies.
$ uv lock
# View the dependency tree for the project.
$ uv tree
Using a tool without installing it:
$ uvx xxx
$ uv tool run xxx
Adding dependency from a source other than a package registry
$ uv add "httpx @ git+https://github.com/encode/httpx"
# requirements.txt
$ uv add -r requirements.txt
Virtual Environment (pip style)
# to create a virtual environment at .venv, with my-name
$ uv venv my-name --python 3.12
$ source .venv/bin/activate
$ deactivate
Check with pip
$ uv pip list
$ uv pip list --format json
$ uv pip check
# lock dependencies declared in a pyproject.toml
$ uv pip compile pyproject.toml -o requirements.txt
$ uv pip compile setup.py -o requirements.txt
# with multiple files
$ uv pip compile pyproject.toml requirements-dev.in -o requirements-dev.txt
Alternative (working on projects with pyproject.toml)
$ uv init <project-name>
# will create a working directory
$ cd <project-name>
# Or initialize a project in the working directory
$ mkdir <project-name>
$ cd <project-name>
$ uv init
# Run the simple main inside the created directory
$ uv run main.py
# Play with your projects, example, adding, removing or upgrading `requests`
$ uv add requests
$ uv remove requests
$ uv lock --upgrade-package requests
# use sync to manually update the environment then activate it before executing a command
$ uv sync
$ source .venv/bin/activate
# without activating the venv, should only run `uv run example.py`
$ python example.py
# build source distributions and binary distributions (wheel) for your project.
$ uv build
# uv will build project in the current directory, and place the built artifacts in a `dist/` subdirectory:
$ ls dist/
Lock file
- uv creates a
uv.lockfile next to the pyproject.toml.uv.lockis a universal or cross-platform lockfile that captures the packages that would be installed across all possible Python markers such as operating system, architecture, and Python version. - The lockfile is automatically created and updated during uv invocations that use the project environment, i.e.,
uv syncanduv run. The lockfile may also be explicitly updated usinguv lock. pylock.tomlis a resolution output format intended to replace requirements.txt (e.g., in the context of uv pip compile, whereby a “locked”requirements.txtfile is generated from a set of input requirements).pylock.tomlis standardized and tool-agnostic, such that in the future,pylock.tomlfiles generated by uv could be installed by other tools, and vice versa.
# export lockfile to pylock.toml
$ uv export -o pylock.toml
# To generate a pylock.toml file from a set of requirements
$ uv pip compile -o pylock.toml -r requirements.in
# To install from a pylock.toml file
$ uv pip install -r pylock.toml
Notes
Locking and syncing are automatic in uv. For example, when uv run is used, the project is locked and synced before invoking the requested command. This ensures the project environment is always up-to-date
# To disable automatic locking
$ uv run --locked ...
# To use the lockfile without checking if it is up-to-date
$ uv run --frozen ...
# To run a command without checking if the environment is up-to-date
$ uv run --no-sync ...
# Check if the lockfile is up-to-date
$ uv lock --check
# Explicitly creat or update lock file
$ uv lock
# Explicitly sync
$ uv sync
# Retain extraneous packages (do not remove any packages that are not present in the lockfile)
$ uv sync --inexact
Dependency caching
uv uses aggressive caching to avoid re-downloading (and re-building) dependencies that have already been accessed in prior runs.
Have caching issues:
$ uv cache clean
$ uv cache clean <package-name>
# --refresh flag to revalidate cached data for all dependencies
# --reinstall to reinstall
$ uv sync --refresh
$ uv pip install --refresh
$ uv sync --reinstall
A temporary cache directory, if --no-cache was requested.
The specific cache directory specified via --cache-dir, UV_CACHE_DIR, or tool.uv.cache-dir. Recommend: change UV_CACHE_DIR for the cache path.
build && publish with a project
$ uv build
$ uv publish
$ uv build
# Build the package in the specified directory
$ uv build <SRC>
# Build the specified package within the current workspace.
$ uv build --package <PACKAGE>
# update to an exact version
$ uv version 1.0.0
# PyPI token with --token, set a username with --username, password with --password
$ uv publish
# Installing your package
# The --no-project flag is used to avoid installing the package from your local project directory.
$ uv run --with <PACKAGE> --no-project -- python -c "import <PACKAGE>"
Build a package if you want to:
- Add commands to the project
- Distribute the project to others
- Use a src and test layout
- Write a library
[!NOTE] Project environment path
UV_PROJECT_ENVIRONMENT, used to configure the project virtual environment path (.venvby default).
Configuration files
- Setting a persistent index URL, add the following to a
pyproject.toml - Setting the index-url under
[tool.uv.pip], as in the followingpyproject.toml, would only affect the uv pip subcommands (e.g.,uv pip install, but notuv sync,uv lock, oruv run):
# pyproject.toml
[[tool.uv.index]]
url = "https://test.pypi.org/simple"
default = true
[tool.uv.pip]
index-url = "https://test.pypi.org/simple"