Getting Started

This tutorial will guide you through installing build and creating your first Python package ready for distribution.

Note

New to Python packaging? Start with the Python Packaging User Guide tutorial to learn how to structure a Python project. This tutorial assumes you already have a project with a pyproject.toml file.

Prerequisites

You need Python 3.10 or later installed on your system. Check your Python version:

$ python --version
Python 3.11.0

Installation

The recommended way to install build is using pip:

$ pip install build

Or, if you prefer to install it in an isolated environment using pipx:

$ pipx install build

For corporate environments or systems with restricted internet access, see Corporate Environments.

Creating a simple package

Let’s create a minimal Python package to demonstrate how build works.

  1. Create a project directory:

$ mkdir mypackage
$ cd mypackage
  1. Create a pyproject.toml file:

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "mypackage"
version = "0.1.0"
description = "A simple example package"
readme = "README.md"
requires-python = ">=3.8"
  1. Create a README.md file:

# My Package

This is a simple example package.
  1. Create your Python package:

$ mkdir src/mypackage
$ touch src/mypackage/__init__.py
  1. Add some code to src/mypackage/__init__.py:

def hello():
    return "Hello from mypackage!"

Building your package

Now you’re ready to build your package:

$ python -m build

You should see output like:

* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - hatchling
* Getting build dependencies for sdist...
* Building sdist...
* Building wheel from sdist
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - hatchling
* Getting build dependencies for wheel...
* Building wheel...
Successfully built mypackage-0.1.0.tar.gz and mypackage-0.1.0-py3-none-any.whl

The built packages are now in the dist/ directory:

$ ls dist/
mypackage-0.1.0-py3-none-any.whl
mypackage-0.1.0.tar.gz

Understanding what happened

Build created two distribution files (packages ready for distribution):

  1. Source distribution: mypackage-0.1.0.tar.gz

    This tarball (compressed archive) contains your source code. Anyone can download it and build your package on their system. Learn more in the source distribution specification.

  2. Wheel: mypackage-0.1.0-py3-none-any.whl

    This wheel is a pre-built package that pip can install directly without needing to build anything. This makes installation much faster.

Build used an isolated environment to ensure your package builds consistently regardless of what you have installed on your computer. It:

  1. Created a temporary virtual environment

  2. Installed only your build dependencies (hatchling)

  3. Invoked the build backend to create the distribution files

  4. Cleaned up the temporary environment when done

Seeing which backend versions were used

build deletes the isolated environment after each build, so it does not leave the installed versions behind. Instead it prints them as it goes:

$ python -m build --wheel
...
* Getting build dependencies for wheel...
* Installed build dependency versions:
  - hatchling==1.30.1
* Building wheel...

build prints each installed build dependency as name==version. Keep this handy when reporting a problem to a backend’s issue tracker, which usually asks for the exact version you built with. See Troubleshooting.

Building a wheel from your sdist

You can also point build at the source distribution you just produced. Build checks the archive and runs a wheel build against its contents, which catches missing files in the sdist:

$ python -m build dist/mypackage-0.1.0.tar.gz
Successfully built mypackage-0.1.0-py3-none-any.whl

The wheel lands next to the sdist. Pass --outdir to write somewhere else. If your package compiles C/C++ and you rebuild often, --sdist-extract-dir keeps the extracted sources at a fixed path so ccache/sccache can reuse earlier compilations; see Basic Usage.

Building without isolation

If you install the build dependencies yourself and build with --no-isolation, build first checks that every declared dependency is present in the interpreter you are running. When something is missing it stops with an Unmet dependencies error that names the interpreter it checked and, for each requirement, the version it wanted against the version it found - so you can tell “not installed” apart from “installed, but the wrong version”. See Troubleshooting for how to read it.

Recording what build produced

If a script or CI job needs the exact filenames build produced, add --report PATH to write them to a JSON file instead of parsing the output:

$ python -m build --report build-report.json

Next steps