aspect_rules_py provides py_library, py_binary, and py_test rules that
behave like standard Python tooling, as an alternative to the community
rules_python ruleset. It
resolves PyPI dependencies from a uv
lockfile and provisions its own hermetic interpreters, so rules_python is
optional.
Create a new project
1
Install the Aspect CLI
2
Scaffold a new project
uv for dependency management and ruff and ty for linting. See aspect init for the full flag reference (presets, --template, --license).Prefer GitHub’s “Use this template” button? Start from aspect-starters/py instead, or git clone https://github.com/aspect-starters/py my-app.3
Set up your dev environment
bazel run //tools:bazel_env, which installs project tools to your PATH. direnv is optional but recommended; without it you have to install tools yourself.4
Add a dependency
Add the package to Depend on it as
pyproject.toml under [project] dependencies, then regenerate uv.lock:@pypi//requests in a BUILD file.5
Build and run
BUILD files are written by hand; see hello/py/BUILD.bazel for the pattern.Explore Bazel with Python
Starter template
Clone the starter repository for a working Bazel + Python setup.Open it in a GitHub Codespace to try it without a local install.
Bazel 102: Python training
A hands-on course for building, testing, and shipping Python with Bazel.Covers dependency pinning, virtualenvs, pytest, linting, and container images.
Key features
- Idiomatic Python behavior. Uses the standard
site-packagesfolder layout instead of manipulating$PYTHONPATH, so your code behaves the same way under Bazel as it does in a normal Python environment. - Real virtualenvs. Each build runs in a virtualenv, which means IDE support (autocomplete, jump-to-definition) works in PyCharm, VS Code, and others without extra configuration.
- Hermetic. The launcher uses Bash rather than Python, so there’s no dependency on a system Python interpreter. Interpreters come from python-build-standalone.
- Cross-platform. Build Linux container images from a Mac, build across architectures, and target custom platforms. Wheels are selected for the target platform, not the host.
- uv instead of pip.
aspect_rules_pyreadsuv.lockdirectly. One lockfile replaces per-platformrequirements.txtfiles, and all downloads go through the Bazel downloader, so private mirrors work.
Ecosystem
Manage dependencies with uv
One lockfile for all platforms. Fast, reproducible installs and cross-platform container builds.
Migrating from rules_python
Already using rules_python? Migration is mostly a drop-in replacement.
Video: Python at Monorepo World
Alex Eagle’s talk, with a demo of rules_py.
Package management with PyPI
Declare direct dependencies inpyproject.toml and pin them with uv lock into a uv.lock file.
The uv module extension in aspect_rules_py reads uv.lock directly and exposes each package as @pypi//<package>:
requirements.txt, pip_compile, or pip.parse step. See Manage dependencies with uv for the full setup, including the .bazelrc venv flag.
Python programs
Usepy_library, py_binary, and py_test for code organization, executables, and tests. Write the BUILD files by hand, or generate them with the aspect-gazelle Python extension, which needs a gazelle_python.yaml manifest generated from your lockfile (see Gazelle integration).
Bazel runs these targets with a hermetic Python toolchain instead of relying on a system interpreter.
API reference:
Python rules |
toolchains |
repositories
Developer workflow
For day-to-day development, Bazel-generated virtualenv targets improve editor integration and local debugging while staying aligned with Bazel’s dependency graph.Monorepo dependencies
In a live-at-HEAD monorepo, local libraries and services depend on each other directly throughdeps, without publishing intermediate package versions.
Keep one @pypi hub for the whole repository. When teams need different versions of the same package, register each dependency set as a [dependency-group] in pyproject.toml and select it per target or per build with the venv flag. See Virtual dependencies.
Course:
Code generation and tools
Python console scripts can be exposed as Bazel tools and invoked from build actions. Usepy_console_script_binary and run_binary to model code generation with explicit inputs and outputs.
Course:
Shipping artifacts
Bazel can package Python applications into OCI images and load them locally for quick verification. For release pipelines, stamping can embed build metadata in otherwise deterministic outputs. Course:Cross-builds
Cross-build scenarios require careful handling of host, exec, and target platforms, especially when dependencies include non-pure Python wheels or source builds. Course:Formatting and linting
The starter uses two commands:- Format tracked files:
- Run lint checks (and apply safe fixes when offered):
pyproject.toml and keep linting in CI so style and correctness checks stay consistent across the team.
API reference:
- ruff - Ruff linter integration. Homepage.
- ty - Ty type-checking integration. Homepage.
- flake8 - Flake8 linter integration. Homepage.
- pylint - Pylint linter integration. Homepage.
Additional APIs
- Unstable APIs: interfaces that may change between releases.
Community
Join the Aspect Community Slack, Aspect’s free community support. Ask in#help for general support. Join the discussion and see what others are building with the Aspect CLI and Aspect Extension Language (AXL) in the #cli and #axl channels.
For Bazel and the Bazel rulesets, Bazel Slack is the best place for support and discussion. Ask about Aspect’s rules_js in #javascript and rules_py in #python.
