Understanding pyproject.toml, setuptools, .whl, and .tar.gz

By Pradyumna Chippigiri

June 15, 2026


Today I learned how modern packaging works in Python.

1. pyproject.toml

pyproject.toml is the main configuration file for a Python project.

It tells Python tools:

Very similar to:

Example: pyproject.toml

[project]
name = "mypackage"
version = "1.0.0"
dependencies = [
    "fastapi",
    "uvicorn"
]
 
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

This does not install dependencies by itself. It only declares them for your project.

Earlier Python packaging was messy and spread across files like:

Now it is centralized in pyproject.toml.

How dependencies get installed

Once dependencies are declared in pyproject.toml, installer tools (usually pip) read them during install.

Common commands:

pip install .
pip install -e .

If you define optional groups (like dev), you can install them with:

pip install -e ".[dev]"

2. What setuptools does

setuptools is the tool that converts Python code into installable/distributable packages.

Think:

Your code -> setuptools -> distributable artifact

Similar to:

Example project

myproject/
|
|- pyproject.toml
`- src/
   `- mypackage/
      |- __init__.py
      `- math_utils.py

3. Building the package

Command:

python -m build

What this does under the hood:

So yes, if pyproject.toml says:

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

then python -m build will use that backend to build your package.

Output

A new folder gets created:

dist/
|
|- mypackage-1.0.0.whl
`- mypackage-1.0.0.tar.gz

4. What are these files?

.whl (Wheel)

Example:

mypackage-1.0.0-py3-none-any.whl

This is the main installable package format in Python.

Equivalent to:

JAR artifact in Java

Users install it using:

pip install mypackage-1.0.0.whl

.tar.gz

This is the source distribution.

Contains:

Used when:

5. Important difference from Java

In Java:

In Python:

because Python is mostly interpreted.

Example wheel contents:

mypackage/
    __init__.py
    math_utils.py

Some libraries like NumPy may also include compiled binaries (.so, .dll) for performance.

PyPI or internal registry

After build, these artifacts are usually published to:

Then consumers install from that registry using pip install ....