Managing Python Versions and Virtual Environments with uv
Most projects we work on require Python 3.9 or greater. Many require a later version. In either case it is necessary to be able to have multiple versions of Python installed and easily switch between them, as well as manage project-specific dependencies. We use uv to handle both Python version management and virtual environments.
Installing uv
Follow uv's recommended installation methods. The quickest way is usually:
curl -LsSf https://astral.sh/uv/install.sh | sh
Or on macOS with Homebrew:
To verify that the installation was successful run the following and ensure that it prints out a version number:
Installing Python Versions
uv can install and manage Python versions directly. To see available Python versions:
uv python list --all-versions
To install a specific Python version:
Or install the latest patch version of a minor release:
uv python install 3.11 # Installs latest 3.11.x
To see which Python versions are currently installed:
Selecting a Python Version for Your Project
When creating a new project, you can specify which Python version to use:
uv init --python 3.11 my-project
cd my-project
For existing projects, uv will use the Python version specified in the pyproject.toml file's requires-python field. You can also specify a Python version when syncing:
Or pin a specific Python version for your project:
This creates a .python-version file in your project directory that uv will respect.
Managing Virtual Environments
uv automatically creates and manages virtual environments for your projects. By default, it creates them in a .venv directory within your project folder.
Creating Virtual Environments
For a new project:
uv init my-project
cd my-project
uv sync
You can also create a project with a specific structure:
uv init --package my-project # Creates a package structure
uv init --app my-project # Creates an application structure
For an existing project with a pyproject.toml file:
This will:
- Create a virtual environment in
.venv
- Install the Python version specified in
pyproject.toml
- Install all project dependencies
Adding Dependencies
Use uv add to add new dependencies to your project:
This updates your pyproject.toml and uv.lock files and installs the package.
For development dependencies:
uv add --dev pytest black mypy
For optional dependency groups:
uv add --group docs sphinx sphinx-rtd-theme
Updating Dependencies
Update a specific package:
Update to a specific version:
Update all packages to their latest compatible versions:
Update only specific packages:
uv sync --upgrade-package requests --upgrade-package urllib3
Inspecting Dependencies
View the dependency tree:
Show outdated packages:
Running Commands
Run commands in the project's virtual environment:
uv run python src/main.py
uv run pytest
uv run black .
For interactive sessions, you can activate the virtual environment:
source .venv/bin/activate # On Unix/macOS
# or
.venv\Scripts\activate # On Windows
python src/main.py # Uses the virtual environment's Python
deactivate # Exit the virtual environment
Advanced Features
Run Python tools without installing them globally:
uv tool run black .
uv tool run --from ruff ruff check
uv tool run --python 3.12 mypy src/
Install tools globally for command-line use:
uv tool install black
uv tool install ruff
Working with Scripts
Run Python scripts with inline dependencies:
uv run --with pandas,matplotlib analysis.py
Create self-contained scripts with dependency declarations:
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "requests",
# "rich",
# ]
# ///
import requests
from rich import print
response = requests.get("https://api.github.com")
print(response.json())
Then run it with:
Working with Requirements Files
Export dependencies to a requirements file:
uv pip compile pyproject.toml -o requirements.txt
Install from a requirements file:
uv pip sync requirements.txt
From pip/venv
If you have a requirements.txt file:
uv init
uv pip sync requirements.txt
uv add --dev <your-dev-packages>
From Poetry
uv can read pyproject.toml files created by Poetry. Simply run:
To fully migrate, you may want to:
- Remove the
[tool.poetry] sections from pyproject.toml
- Delete
poetry.lock
- Run
uv sync to generate uv.lock
Further Reading
Edit