Python projects often begin with a familiar sequence: create a virtual environment, upgrade pip, install packages, and save dependencies in a requirements.txt file. That workflow works, but it can involve several separate tools and commands.
uv is a fast Python package and project manager created by Astral. It can replace much of the day-to-day workflow around pip, venv, and tools such as pipx, while also generating a lockfile that records the exact dependency versions selected for a project.
Why Use uv?
uv is useful when you want a simpler and more reproducible Python workflow.
- It creates and manages virtual environments for projects.
- It installs packages quickly using a global cache.
- It manages project dependencies in
pyproject.toml. - It generates
uv.lockso installations can be reproduced. - It can run commands in a project environment without manual activation.
- It can install and run standalone Python tools.
uv does not remove the need to understand Python environments. Instead, it puts common environment and dependency operations behind a consistent command-line interface.
Install uv
On Windows, install uv with PowerShell:
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
On macOS or Linux, use the shell installer:
curl -LsSf https://astral.sh/uv/install.sh | sh
You can also install uv with a package manager. For example, Homebrew users can run:
brew install uv
Confirm that the installation works:
uv --version
Restart your terminal if the uv command is not found immediately after installation.
Create a Python Project
Create a new project with uv init:
mkdir weather-app
cd weather-app
uv init
This creates a basic project structure, including a pyproject.toml file and a Python entry point. The exact files may vary depending on the options you provide, but pyproject.toml is the central configuration file for the project.
You can specify a project name directly:
uv init --name weather-app
To start with a particular Python version, use the --python option:
uv init --python 3.12
If that Python version is not installed locally, uv can download a managed copy when needed.
Add and Remove Dependencies
Add a package with uv add:
uv add requests
This updates pyproject.toml, resolves compatible versions, and updates uv.lock. Add several packages at once when they belong to the same feature:
uv add pandas matplotlib
Development-only dependencies can be placed in a development dependency group:
uv add --dev pytest ruff
Remove a package with:
uv remove requests
To install a specific version range, include it in the requirement:
uv add "django>=5.0,<6"
Run Your Project
Use uv run to execute a command in the project environment:
uv run main.py
For a package configured as a project script, run its script name instead. For example, if pyproject.toml contains a script named start, use:
uv run start
You can also run development tools without manually activating the virtual environment:
uv run pytest
uv run ruff check .
This is one of the most convenient parts of the workflow. The command makes it clear which project environment should provide the tool and its dependencies.
Understand uv.lock and uv sync
The uv.lock file records the resolved versions of the project’s direct and transitive dependencies. Commit it to version control so other developers and deployment systems can reproduce the same environment.
To synchronize the environment with the project files and lockfile, run:
uv sync
For a reproducible installation in continuous integration, use the locked dependencies without changing the lockfile:
uv sync --locked
When pyproject.toml changes, run uv lock or uv sync to resolve the updated dependency set and review the resulting lockfile changes.
Use a Virtual Environment Directly
Most project workflows do not require manual activation, but uv can create a virtual environment explicitly:
uv venv
The default environment is created in a .venv directory. Activate it using the command for your operating system if you want to work with ordinary python and pip commands.
Windows PowerShell:
.venv\Scripts\Activate.ps1
macOS and Linux:
source .venv/bin/activate
For a project managed with pyproject.toml, prefer uv add, uv remove, uv sync, and uv run so the configuration and lockfile stay up to date.
Install Standalone Python Tools
uv can install command-line tools in isolated environments. For example:
uv tool install ruff
You can also run a tool without permanently installing it:
uvx ruff check .
This is helpful for occasional tools or for trying a command before adding it to a project.
A Practical Daily Workflow
A small project might use this sequence:
uv init --python 3.12
uv add requests
uv add --dev pytest ruff
uv run pytest
uv run ruff check .
uv sync --locked
Commit both pyproject.toml and uv.lock. Do not commit .venv, because it is a local generated environment and can be recreated with uv sync.
Migrating from requirements.txt
If an existing project already has a requirements.txt file, create or enter the project directory and add the listed requirements:
uv init
uv add -r requirements.txt
Review the resulting pyproject.toml and uv.lock files before removing the old requirements file. If deployment or another tool still expects requirements.txt, keep generating or maintaining that file until the rest of the project has moved to the new workflow.
Common Commands Cheat Sheet
| Command | Purpose |
|---|---|
uv init | Create a Python project |
uv python install 3.12 | Install a managed Python version |
uv venv | Create a virtual environment |
uv add package | Add a project dependency |
uv add --dev package | Add a development dependency |
uv remove package | Remove a project dependency |
uv sync | Synchronize the environment with the project |
uv sync --locked | Synchronize without changing the lockfile |
uv run command | Run a command in the project environment |
uv lock | Resolve and update the lockfile |
uv tool install tool | Install a standalone Python tool |
uvx tool | Run a tool in a temporary environment |
Final Thoughts
uv brings project initialization, Python versions, virtual environments, dependencies, lockfiles, and command execution into one workflow. It is a strong choice for new Python projects and a practical way to simplify existing projects that rely on several separate commands.
The most important habit is to treat pyproject.toml as the project’s dependency declaration and uv.lock as the reproducibility record. With those files committed, a new environment can be recreated with a single uv sync command.
