Recommended Free Tools
For a new Python package, start with a pyproject.toml, choose a build backend that fits the package, and use a frontend such as build to create a wheel and source distribution. The frontend runs the build; the backend decides how your project becomes distributable files. The right backend depends on your layout, compatibility needs, and whether you compile native code.
What Python build tools do
Python packaging uses separate tools for separate jobs. A build frontend reads the project configuration, prepares the build environment, and calls the standardized build hooks. A build backend implements those hooks and handles packaging-specific work such as discovering files, generating metadata, and creating distribution archives. The Python Packaging Authority’s explanation of build backends describes this division; its build workflow documentation explains how a frontend invokes the backend.
This separation lets a frontend work with different backends. Changing the frontend does not, by itself, change how a backend includes files or supports a particular project layout.
What you build
- A wheel is a built distribution intended for installation. Its contents and metadata depend on the backend and project configuration.
- A source distribution (sdist) is an archive of source material used to build or inspect a release. It should contain the files needed for that purpose.
Do not assume that a successful build proves the archives contain everything you intend to distribute. Inspect both outputs before publishing.
#1 Best Overall
Which Python build backend should you use?
Choose based on the package you have and the workflow you need, not on an assumed speed or popularity ranking. The candidates below are use-case distinctions in the PyPA backend guide, not performance benchmarks.
| Project or workflow | Candidate | Trade-off to consider |
|---|---|---|
| Straightforward pure-Python package | Flit-core or Hatchling | Both suit relatively simple packages. Hatchling supports plugins and common layout conventions. |
| Broad compatibility, customization, C extensions, namespace packages, or entry points | Setuptools | Mature and capable, but its configuration can involve more legacy concepts and complexity. |
| C or C++ extension built with CMake | scikit-build-core | Designed to integrate package builds with CMake and modern package metadata. |
| Extension project already using Meson | meson-python | Integrates packaging with the existing Meson build system. |
| Existing Poetry-centered workflow | Poetry / poetry-core | May fit the surrounding ecosystem. Custom [tool.poetry] metadata can be less interoperable in some contexts. |
| PDM workflow or a need for dynamic metadata or build hooks | pdm-backend | Supports standard metadata as well as backend-specific features. |
Confirm current capabilities in the chosen backend’s documentation before migrating or relying on a specialized feature. Backend features and supported versions can change.
Configure a package with pyproject.toml
pyproject.toml is the central modern configuration file. Its [build-system] table declares the backend and the packages needed to run it; [project] holds standard project metadata; and [tool] tables hold settings specific to individual tools. The PyPA guide to writing pyproject.toml recommends using [project] metadata for new projects.
Minimal Hatchling example
This example shows the shape of a project configuration. The version constraint is an example, not a permanent compatibility guarantee; check the backend’s documentation for the version appropriate to your project.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "example-package"
version = "0.1.0"
description = "An example Python package"
readme = "README.md"
requires-python = ">=3.9"
license = "MIT"
dependencies = []
Use a license expression and license-file configuration supported by the backend version you select. The pyproject.toml specification defines license as an SPDX license expression and license-files as paths or glob patterns for legal notices included in distribution archives. Support is version-specific: the PyPA guide lists PEP 639 support thresholds of Hatchling 1.27.0, setuptools 77.0.3, Flit-core 3.12, pdm-backend 2.4.0, poetry-core 2.2.0, and uv-build 0.7.19. Treat these as the thresholds stated by that guide, not as a substitute for checking current backend documentation.
Rank #2
Other backend declarations
The backend import path and build requirements must match the backend you choose. The PyPA guide currently gives these example declarations; its listed versions are guide values and may change:
| Backend | build-backend |
Typical requirement name |
|---|---|---|
| Hatchling | hatchling.build |
hatchling |
| Setuptools | setuptools.build_meta |
setuptools |
| Flit | flit_core.buildapi |
flit_core |
| PDM | pdm.backend |
pdm-backend |
| uv-build | uv_build |
uv_build |
Copy the declaration and compatible requirement from the selected backend’s current documentation rather than combining an import path from one backend with another backend’s requirement.
Project metadata and tool-specific settings
Put standard fields such as project name, version, dependencies, and supported Python versions in [project] when the backend supports them. Put backend-only configuration under its corresponding [tool.*] table. This makes the standard project information more portable than putting all metadata in a backend-specific format.
Setuptools continues to support legacy setup.py and setup.cfg configurations; they remain valid for compatibility and special cases. Poetry supported only its [tool.poetry] metadata format before version 2.0, released January 5, 2025, and supports [project] from version 2.0 onward. If you use Poetry, check the exact version and configuration format in use before assuming standard metadata will be read.
Build a wheel and source distribution
A common frontend is the build package. From the project root, install it and run the build in an environment where Python and pip are available:
python -m pip install build
python -m build
When configured with a supported backend, the frontend uses the requirements in [build-system] to prepare an isolated build environment and invokes the backend’s hooks. The default build produces a wheel and an sdist in dist/. The exact build requirements and packaging behavior still come from your configuration and backend.
Review the release artifacts
- Open the wheel and sdist from
dist/and check that expected modules, documentation, and legal notices are present. - Check that generated metadata contains the intended project name, version, dependencies, and Python compatibility information.
- Confirm that tests or examples needed by your release process are included where intended, and that local files or secrets are not accidentally packaged.
- Test installation of the wheel in a clean environment and test rebuilding from the sdist if users or release systems will rely on source builds.
The PyPA packaging tutorial presents a starter layout with a license, pyproject.toml, README, a src/ package, and a tests/ directory. A backend’s capabilities affect whether that layout, extensions, and other project-specific needs are supported as expected.
Common problems and how to troubleshoot them
Build backend cannot be imported
Check that build-backend is spelled exactly as the backend documents it and that the corresponding package is listed in [build-system].requires. A missing build requirement or a mismatched backend path prevents the frontend from calling the backend.
Metadata is missing or rejected
Confirm that the backend version supports the metadata format you used, and that standard fields are in [project] rather than only in a tool-specific table when you expect portable metadata. For license expressions and license-file patterns, verify PEP 639 support against the version thresholds and current backend documentation.
Files are absent from the wheel or sdist
File discovery and inclusion are backend responsibilities. Review that backend’s rules and configuration, rebuild, and inspect each archive; do not infer the contents of one artifact from the other.
Native extension does not build
Check that the backend fits the native build system: scikit-build-core for a CMake-based extension, meson-python for a Meson project, or setuptools where its extension and customization support fits. Also check the native toolchain and build prerequisites required by the project; a Python backend alone does not supply every compiler or system dependency.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsA legacy project behaves differently after migration
Compare the old configuration’s metadata and file-selection behavior with the new backend’s configuration, then inspect and test both artifacts. Legacy setuptools configuration remains valid, so migration is a choice rather than a prerequisite for building a package.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Performance, reliability, and cost considerations
The available documentation establishes a standards-based workflow and backend capability differences, but it does not establish a universal speed ranking or adoption statistic. Build time depends on the project and its dependencies, particularly when compiling extensions; measure your own release workflow if build speed is a deciding factor.
Build isolation helps the frontend provide the backend’s declared build requirements separately from the active environment. It does not guarantee that the package metadata or archive contents are correct. Inspecting and testing the built wheel and sdist is part of a reliable release process.
The sources cited here do not establish a comparative pricing table for these tools. Check each project’s current terms for any paid services or hosted features rather than assuming that backend choice implies a particular cost.
Best Value
ScreenshotNeo is a separate tool, not a Python package builder
ScreenshotNeo is a website screenshot API and MCP server, not a Python build frontend or backend, so it does not replace python -m build or create wheels and sdists. If a separate task in your developer workflow is capturing web pages, ScreenshotNeo offers a one-request screenshot API and an MCP server for AI agents; its clean-shot, billing, and plan details are specific to that screenshot service.
Sign up for ScreenshotNeo to get 1,000 screenshots a month free with no card required.
Frequently Asked Questions
Does pyproject.toml replace requirements.txt?
No. They serve different roles: pyproject.toml describes project metadata and build configuration, while a requirements file is commonly used to specify packages to install in an environment.
Can one project use a different build frontend without changing its backend?
Often, yes. Frontends and backends are separate components, but the frontend must support the backend’s standardized hooks and the project’s configuration.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




