Skip to main content
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.
Stuck?

Create a new project

1

Install the Aspect CLI

For other installation methods, see Aspect CLI.
2

Scaffold a new project

A working Bazel + Python setup with 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

Follow the prompts to run 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 pyproject.toml under [project] dependencies, then regenerate uv.lock:
Depend on it as @pypi//requests in a BUILD file.
5

Build and run

The starter’s Python 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-packages folder 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_py reads uv.lock directly. One lockfile replaces per-platform requirements.txt files, 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 in pyproject.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>:
There’s no requirements.txt, pip_compile, or pip.parse step. See Manage dependencies with uv for the full setup, including the .bazelrc venv flag.
After changing dependencies, repin before building. In the starter template, ./tools/repin runs bazel run @uv — lock and updates MODULE.bazel.lock.

Python programs

Use py_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 through deps, 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. Use py_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:
  1. Format tracked files:
  2. Run lint checks (and apply safe fixes when offered):
Configure tool behavior in pyproject.toml and keep linting in CI so style and correctness checks stay consistent across the team. API reference:

Additional APIs

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.