How to Build a Wheel with Hatchling in Python

Build a Python wheel using the hatchling build backend and the build package, handling missing project metadata automatically.

Easy Python 3.9+ Aug 9, 2026 Modern tooling 14 views 0 copies

Requires third-party packages — install first
pip install build

Python code

44 lines
Python 3.9+
import subprocess
import sys
import tempfile
from pathlib import Path


def build_wheel_with_hatchling(project_dir: str) -> str:
    """Build a wheel using hatchling and return the wheel file path."""
    project_path = Path(project_dir)

    # Simulate a minimal project structure if missing
    if not (project_path / "pyproject.toml").exists():
        pyproject = """[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "demo"
version = "0.1.0"
"""
        (project_path / "pyproject.toml").write_text(pyproject)
        (project_path / "src" / "demo").mkdir(parents=True, exist_ok=True)
        (project_path / "src" / "demo" / "__init__.py").write_text('__version__ = "0.1.0"\n')

    # Build the wheel
    result = subprocess.run(
        [sys.executable, "-m", "build", "--wheel", "--outdir", str(project_path / "dist")],
        cwd=str(project_path),
        capture_output=True,
        text=True,
        check=False,
    )

    if result.returncode != 0:
        raise RuntimeError(f"Build failed: {result.stderr}")

    wheel_files = list((project_path / "dist").glob("*.whl"))
    return str(wheel_files[0]) if wheel_files else "No wheel file produced"


if __name__ == "__main__":
    with tempfile.TemporaryDirectory() as tmpdir:
        wheel_path = build_wheel_with_hatchling(tmpdir)
        print(f"Built wheel: {wheel_path}")

Output

stdout
Built wheel: /tmp/tmpxyz123/dist/demo-0.1.0-py3-none-any.whl

How it works

The script creates a minimal pyproject.toml with hatchling as the build backend if one doesn't exist. It invokes the build module via subprocess, which handles the wheel creation following PEP 517. The --wheel flag restricts the build to just the wheel artifact, and --outdir controls where the output lands. The function returns the path to the first .whl file found in the dist directory, or a message if none was produced. Using subprocess.run with check=False lets the script capture and surface the real error message when the build fails.

Common mistakes

  • Forgetting that `pip install build` is required because the `build` module is not in the standard library
  • Not creating the src layout directory before building when using a pure src layout
  • Ignoring the stderr output when the build fails, which hides useful diagnostics
  • Assuming a wheel was produced without verifying the return code first

Variations

  1. Use `python -m build --sdist` to build a source distribution instead of a wheel
  2. Pass `--wheel` and `--sdist` together to build both artifacts in one command

Real-world use cases

  • CI pipelines that build and publish Python packages to PyPI after every merge to main.
  • Automated release scripts that generate wheels for internal package registries within an organization.
  • Local development workflows that check whether a package builds cleanly before pushing code changes.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Modern tooling

Related tutorials and quizzes for this topic.