Code of the Day
AdvancedTooling & Packaging

Packaging with pyproject

Turn your code into an installable, shareable package.

PythonAdvanced8 min read
By the end of this lesson you will be able to:
  • Describe a project with pyproject.toml
  • Explain what metadata and dependencies a package declares
  • Build and (optionally) publish a package

When code outgrows a folder of scripts — you want to install it, version it, or share it — you . The modern standard is a single pyproject.toml file that describes the project: its name, version, dependencies, and how to build it. It's the manifest from the project-shape lesson, in Python's current form.

pyproject.toml

One declarative file replaces the older scattered setup files:

[project]
name = "mytool"
version = "0.1.0"
description = "A small, useful tool"
requires-python = ">=3.11"
dependencies = [
    "requests>=2.31",
]

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

The [project] table is your package's identity and its dependency contract (note the version ranges — the manifest, distinct from the pinned lockfile). [build-system] tells tools how to build it.

Building and publishing

With that file, standard tools turn your code into distributable artifacts:

python -m build        # produces a wheel (.whl) and source archive in dist/
python -m twine upload dist/*   # publish to PyPI (so others can pip install it)

A wheel is the built, ready-to-install format pip prefers — the packaging equivalent of the build-and-release lesson's "build once, install anywhere."

Dependencies vs lockfile, again

Two layers, same distinction as before:

  • pyproject.toml declares dependencies as ranges — what your package needs to work.
  • A lockfile (from pip freeze, or tools like uv/poetry) records the exact versions for a reproducible build.

Libraries publish ranges so they compose with others; applications also pin exact versions so deployments are deterministic.

You don't need to publish to PyPI to benefit — installs your project locally in "editable" mode, so imports work cleanly across your own modules while you develop.

Where to go next

Last in this module, the tool that proves your package works: testing with pytest.

Finished reading? Mark it complete to track your progress.

On this page