aspect_rules_py provides its own Python interpreter provisioning, backed by
python-build-standalone
(PBS). This replaces the need to use rules_python’s python.toolchain() for
interpreter management.
No version manifests. Unlike rules_python, there is no checked-in table of
SHA256 hashes or version metadata to maintain. Interpreter versions and checksums
are discovered automatically from PBS release artifacts and cached in your
MODULE.bazel.lock.
Easy updates. To get new interpreter versions, add a PBS release date—no
repinning or manifest regeneration required.
No editorial decisions. Any PBS release exposes every version it contains.
Need Python 3.8? Add an older release date that includes it.
Windows and cross-platform support. Nine platforms are registered out of the box, including Windows on x86_64, aarch64, and i686, Linux with glibc and musl, and macOS.
Quickstart
Add the following to yourMODULE.bazel:
Configuring releases
By default, the extension ships with a small set of release dates covering the full range of available Python versions. Useconfigure() to pin to specific
releases or to include versions that have been dropped from newer releases:
configure() tag, and only the root module’s tag takes effect. Dependency modules may include configure() without error, but the extension silently ignores it.
Using the latest release
For development workflows where you always want the newest PBS release:Using a mirror or fork
If you host PBS releases on a mirror or maintain your own fork:base_url must point to a directory structure matching PBS releases, where
{base_url}/{date}/SHA256SUMS and {base_url}/{date}/{asset} are valid paths.
Module scoping
Only the root module’sconfigure() tag and is_default and pre_release flags on toolchain() take effect. This gives the root module full control over the build environment while allowing dependency modules to declare which Python versions they need.
The following table shows which settings each module type controls:
If a dependency module requests a Python version that no root-module release includes, the build fails with a clear error message identifying which module requested it.
Selecting Python versions
There are three layers of version control, from broadest to most specific.Default version (MODULE.bazel)
Bazel selects theis_default = True toolchain when nothing else overrides it:
Build-wide default (.bazelrc)
Set--@aspect_rules_py//py:python_version in .bazelrc to lock the entire
build to a specific version. This is good practice even when it matches the
is_default toolchain—it makes the choice explicit and visible in version
control:
Per-target overrides (python_version attribute)
Individualpy_binary, py_venv_binary, py_test, and py_venv_test targets
can pin to a specific version using the python_version attribute, which takes
precedence over the flag:
Precedence
The most specific setting wins:python_version attribute > flag > default toolchain.
Build configurations
PBS provides several build configurations that control how the Python interpreter itself is compiled. The right choice depends on your priorities: binary size, debug support, or experimental features like free-threading. The default isinstall_only, which uses PGO+LTO compilation on platforms that
support it. PGO (Profile-Guided Optimization) and LTO (Link-Time Optimization)
produce a faster interpreter by letting the compiler optimize across the entire
program using real runtime behavior. This configuration suits most use cases.
Use install_only_stripped to reduce binary size by removing debug symbols,
which is useful in environments where disk space or distribution size matters.
The freethreaded configurations disable the GIL (Global Interpreter Lock),
allowing true parallel execution across threads. Free-threading is experimental
and was introduced in Python 3.13. Use these configurations only if you are
explicitly targeting the free-threaded build and your dependencies support it.
Select a configuration per toolchain using the build_config attribute:
Platforms
These platforms are available by default:
Not all Python versions are available on all platforms. The toolchain resolver silently skips unavailable combinations.
Compatibility with rules_python
This interpreter provisioning is designed to coexist withrules_python:
- Toolchain registration uses the standard
@bazel_tools//tools/python:toolchain_type, so these interpreters work with all existing Python rules. - Build transitions keep the
@rules_python//python/config_settings:python_versionflag in sync withaspect_rules_py’s own version flag. aspect_rules_pyusespy_runtimeandpy_runtime_pairfromrules_pythonto create the runtime providers.
python.toolchain() calls with
interpreters.toolchain() and remove the rules_python interpreter
configuration while keeping everything else unchanged.
