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:
3matches the latest Python 3 release available. - Major.minor:
3.12matches the latest patch of Python 3.12. - Major.minor.patch:
3.12.3requests 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:
cpythonorcpselects any available CPython version. - Implementation @ version:
[email protected]combines implementation and version. - Concatenated form:
cpython3.12orcp312for 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
tfor free-threaded (no GIL) ordfor debug builds.3.13trequests free-threaded CPython 3.13.3.12.0drequests a debug build.
- Explicit variant: Use the
+syntax for clarity.3.13+freethreadedor3.14+gilto 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 onPATH) - 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:
- Direct paths (filesystem checks)
- Installed managed toolchains
- 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →