How to Specify Python Versions in uv: Complete Syntax Guide

uv accepts over 15 distinct formats for specifying Python versions, ranging from simple strings like 3.12 to full distribution specifications like cpython-3.12.3-macos-aarch64-none and direct filesystem paths.

The astral-sh/uv toolchain provides a sophisticated version parsing system that normalizes diverse request formats into structured PythonVersionRequest objects. Whether you are creating virtual environments with uv venv, installing interpreters via uv python install, or running commands with uv run, understanding the available syntax for specifying Python versions in uv ensures precise control over interpreter selection.

Simple Version Strings

The most common approach uses plain version numbers that match against installed or downloadable Python releases.

  • Major only: 3 matches the latest Python 3 release available.
  • Major.minor: 3.12 matches the latest patch of Python 3.12.
  • Major.minor.patch: 3.12.3 requests an exact release.

# Create a venv with the latest Python 3.12 patch

uv venv --python 3.12

# Install a specific patch version

uv python install 3.11.9

Version Specifiers and Ranges

For flexible constraints, uv accepts PEP 440 version specifiers that define acceptable ranges rather than fixed versions.


# Install any Python version between 3.9 and 3.10

uv python install '>=3.9,<3.10'

# Create a venv with at least Python 3.12

uv venv --python '>=3.12'

These specifiers are parsed in crates/uv-python/src/python_version.rs and normalized into internal constraint objects that drive the resolution logic.

Implementation-Specific Requests

uv supports multiple Python implementations beyond CPython. You can request specific implementations using several syntax variants.

  • Implementation name only: cpython or cp selects any available CPython version.
  • Implementation @ version: [email protected] combines implementation and version.
  • Concatenated form: cpython3.12 or cp312 for compact specification.

# Request CPython specifically

uv venv --python [email protected]

# Compact notation

uv python install cp313

Build Variants: Free-Threaded and Debug Builds

Modern Python distributions include specialized builds identified by suffixes or explicit markers.

  • Short suffix: Append t for free-threaded (no GIL) or d for debug builds.
    • 3.13t requests free-threaded CPython 3.13.
    • 3.12.0d requests a debug build.
  • Explicit variant: Use the + syntax for clarity.
    • 3.13+freethreaded or 3.14+gil to explicitly request GIL-enabled or disabled builds.

# Free-threaded Python 3.13

uv python install 3.13t

# Debug build via explicit variant

uv venv --python 3.12+debug

Full Distribution Specifications

For reproducible environments or CI pipelines, uv accepts complete distribution identifiers that specify platform and architecture.

The format follows: implementation-version-os-arch-libc


# Exact distribution specification

uv python install cpython-3.12.3-macos-aarch64-none

This format ensures you receive the exact binary used in production, avoiding subtle differences between patch releases or build configurations.

Direct Executable Paths and Local Installations

When you need to use a Python interpreter that uv did not manage, specify the path directly.

  • Absolute path: /opt/homebrew/bin/python3
  • Executable name: mypython3 (must exist on PATH)
  • Installation directory: /some/environment/ (directory containing the Python installation)

# Use a specific binary

uv venv --python /usr/local/bin/python3.10

# Reference by directory

uv run --python /opt/python3.12/ script.py

How uv Parses Version Requests

Internally, uv normalizes all these formats through the PythonVersion type defined in crates/uv-python/src/python_version.rs. The parser converts textual requests into structured PythonVersionRequest objects that drive discovery, download, and selection logic.

According to the Python versions concept documentation, uv evaluates version requests in the following priority:

  1. Direct paths (filesystem checks)
  2. Installed managed toolchains
  3. Downloadable releases matching the specification

The resolver logic in crates/uv-resolver/src/python_requirement.rs uses these parsed requests to enforce requires-python constraints during dependency resolution, while CLI commands in crates/uv-cli/src/commands/python.rs handle the initial argument parsing.

Summary

  • Simple versions (3.12, 3.12.3) target specific releases or the latest patch.
  • PEP 440 specifiers (>=3.12,<3.13) define acceptable version ranges.
  • Implementation markers ([email protected], cp312) select specific Python flavors.
  • Build variants (3.13t, +debug, +freethreaded) access specialized CPython builds.
  • Full distribution specs (cpython-3.12.3-macos-aarch64-none) ensure exact binary reproducibility.
  • Direct paths bypass uv's managed toolchain logic for custom installations.

Frequently Asked Questions

Can I use pyenv-style version strings like 3.12.0 in uv?

Yes, uv accepts standard semantic version strings including major-only (3), major-minor (3.12), and full patch (3.12.3) specifications. These are resolved against available managed toolchains or downloaded on demand. Unlike pyenv, uv does not require explicit installation before use; it can automatically fetch missing versions when running commands like uv venv or uv run.

How do I request a free-threaded Python build without the GIL?

Use the short suffix t (e.g., 3.13t) or the explicit variant syntax +freethreaded (e.g., 3.13+freethreaded). Both formats instruct uv to download or select the experimental no-GIL build of CPython. Note that free-threaded builds are currently available for Python 3.13+ and require specific platform support.

What is the difference between [email protected] and cpython-3.12.3-macos-aarch64-none?

The @ syntax ([email protected]) specifies an implementation and version constraint, allowing uv to select any matching installed or downloadable release. The full distribution spec (cpython-3.12.3-macos-aarch64-none) is an exact platform-triple identifier that pins the operating system, architecture, and libc implementation, ensuring binary reproducibility across environments.

Can I point uv to a Python installation it did not manage?

Yes, using direct path specifications. Provide an absolute path to the executable (/usr/local/bin/python3), an installation directory (/opt/python3.12/), or an executable name available on PATH (python3.11). When using direct paths, uv bypasses its managed toolchain logic and uses the specified interpreter directly, though features like automatic downloads will not apply.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →