Harness the Combinatoric Power of Command-Line Tools and Utilities

../Tutorials

Manage Python Projects and Environments With uv

Python Tools

Published March 20, 2026

View as Markdown

Introduction

If you work with Python, you’ve juggled several tools while you worked: pyenv to install Python versions, venv to create virtual environments, and pip to install packages. uv replaces these with a single command-line tool that handles Python version management, virtual environments, and dependency resolution in one place.

In this tutorial you’ll install uv, use it to manage Python versions, create a project with a virtual environment, and manage your dependencies. Then you’ll run one-off scripts.

What You Need

To complete this tutorial, you need:

  • Python installed, which you can do by following the Install Python tutorial.
  • On macOS, you need Homebrew installed, which you can do by following the Install Homebrew tutorial.

Installing uv

On macOS, you can install uv with Homebrew:

brew install uv

On Linux and macOS, you can also install uv with the official installer:

curl -LsSf https://astral.sh/uv/install.sh | sh

On Windows, use the PowerShell installer:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Verify it’s installed:

uv --version
uv 0.10.10 (Homebrew 2026-03-13)

With uv installed, you can use it to install and manage Python versions on your system.

Managing Python Versions

Use uv python list to see which Python versions are available to install:

uv python list

This shows installed versions and versions available for download:

cpython-3.15.0a7-macos-aarch64-none                 <download available>
cpython-3.15.0a7+freethreaded-macos-aarch64-none    <download available>
cpython-3.14.3-macos-aarch64-none                   /opt/homebrew/bin/python3.14 -> ../Cellar/python@3.14/3.14.3_1/bin/python3.14
cpython-3.14.3-macos-aarch64-none                   /opt/homebrew/bin/python3 -> ../Cellar/python@3.14/3.14.3_1/bin/python3
...

Install a specific version with the uv python install command:

uv python install 3.12

uv searches and pulls down the specified version. You don’t need to configure your shell or manage shims like you would with pyenv.

Searching for Python versions matching: Python 3.12
Installed Python 3.12.9 in 2.84s
 + cpython-3.12.9

Now that you have a Python version installed, you can create a new project that uses it.

Creating a Project

Use uv init to create a new project:

uv init myproject

uv creates a directory, along with some default files:

Initialized project `myproject` at /Users/brianhogan/myproject

Switch to the project directory uv created:

cd myproject

List the files uv created, and be sure to list the hidden ones:

ls -la
total 16
drwxr-xr-x  8 brianhogan staff 256 Mar 20 17:11 .
drwxr-xr-x 21 brianhogan staff 672 Mar 20 17:11 ..
drwxr-xr-x  9 brianhogan staff 288 Mar 20 17:11 .git
-rw-r--r--  1 brianhogan staff 109 Mar 20 17:11 .gitignore
-rw-r--r--  1 brianhogan staff   5 Mar 20 17:11 .python-version
-rw-r--r--  1 brianhogan staff   0 Mar 20 17:11 README.md
-rw-r--r--  1 brianhogan staff  86 Mar 20 17:11 main.py
-rw-r--r--  1 brianhogan staff 154 Mar 20 17:11 pyproject.toml

The pyproject.toml file is the project’s configuration. Open it and you’ll see uv has set up the basics:

[project]
name = "testproj"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.14"
dependencies = []

The .python-version file pins the Python version for this project. When you or anyone on your team runs uv commands in this directory, it uses the version specified in that file.

To run the project’s main.py file, use uv run:

uv run main.py
Using CPython 3.14.3 interpreter at: /opt/homebrew/opt/python@3.14/bin/python3.14
Creating virtual environment at: .venv
Hello from testproj!

The first time you run the project, uv creates a virtual environment in .venv and installs any dependencies. You don’t need to create or activate the virtual environment manually.

With the project set up, you can start adding dependencies.

Adding Dependencies

Use uv add to add a package to your project:

uv add requests
Resolved 6 packages in 657ms
Prepared 5 packages in 319ms
Installed 5 packages in 7ms
 + certifi==2026.2.25
 + charset-normalizer==3.4.6
 + idna==3.11
 + requests==2.32.5
 + urllib3==2.6.3

The uv tool resolves the dependency tree, installs the packages into the virtual environment, and updates pyproject.toml and a uv.lock lock file. The lock file pins exact versions so that every team member and your CI system get identical dependencies.

Check your pyproject.toml to see the change:

cat pyproject.toml
[project]
name = "testproj"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.14"
dependencies = [
    "requests>=2.32.5",
]

To remove a package, use uv remove. Remove the requests package you just added:

uv remove requests
Resolved 1 package in 6ms
Uninstalled 5 packages in 8ms
 - certifi==2026.2.25
 - charset-normalizer==3.4.6
 - idna==3.11
 - requests==2.32.5
 - urllib3==2.6.3

This removes the package and its unused dependencies.

You can also add development dependencies that aren’t needed in production. For example, add pytest as a development dependency with the following command:

uv add --dev pytest

This adds pytest under a separate [dependency-groups] section in pyproject.toml, keeping your production dependencies separate from your development dependencies.

These features handle most day-to-day work, but uv can also run one-off commands with packages you haven’t added to the project.

Running Scripts and Tools

You can use uv to run Python scripts and command-line tools without installing them or adding them as project dependencies. This is useful for one-off tasks like formatting code or running a linter.

Use the uvx to run a tool directly. Try using uvx to run ruff, a fast Python linting tool:

uvx ruff check .

The package installs and runs:

Installed 1 package in 3ms
All checks passed!

The uvx command downloads the tool into a temporary environment, runs it, and cleans up. You get the tool you need without polluting your project’s dependencies.

You can also use uv run with inline script dependencies. Create a file called fetch.py:

# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx"]
# ///

import httpx

response = httpx.get("https://httpbin.org/json")
print(response.json()["slideshow"]["title"])

The comment block at the top is a Python Enhancement Proposal (PEP) 723 inline metadata declaration. When you run this script with uv run, it reads those dependencies and installs them into an isolated environment:

uv run fetch.py
Installed 6 packages in 7ms
Sample Slide Show

This lets you share self-contained scripts that declare their own dependencies.

Conclusion

The uv tool gives you a single command for Python version management, virtual environments, and dependency resolution. Your pyproject.toml and uv.lock files capture the full environment, making it possible to share consistent setups across your team, regardless of whether you’re on macOS, Windows, or Linux.