Geekflare is supported by our audience. We may earn affiliate commissions from buying links on this site.
Share on:

Python’s pyproject.toml: An Overview

pyproject.toml
Invicti Web Application Security Scanner – the only solution that delivers automatic verification of vulnerabilities with Proof-Based Scanning™.

Sharing code and collaborating on open-source software has been transformational in software development. It has enabled developers to build more complicated applications with smaller teams using existing packages and libraries.

In the Python ecosystem, most packages are registered on the Python Package Index (PyPI). Using the index, developers can share their code as packages for other developers. To create your own package and upload it to PyPI, you will need a pyproject.toml file. This article is a guide on how it works.

What is pyproject.toml?

Before we get to what the file is, let us first understand the gap it is trying to fill. When you upload a package to PyPI, it will become installable using pip. For example, if your package is called example-package after uploading to PyPI, it would be installable using the command:

pip install example-package

When publishing packages to the Python Package Index, you upload a .whl file. But when you write code, you mostly write .py files, so how do you generate a .whl file? You use a build tool such as setuptools or poetry.

This tool will take your source code and convert it to a .whl file that can be uploaded. As mentioned before, there are multiple tools you can use to generate a whl file. To specify which tool you want Python to use, you write it in the pyproject.toml file.

Therefore, the pyproject.toml file is a file that specifies how your Python project should be built into a package. In addition to that, you can provide additional information, such as your package’s metadata, that will be displayed on your package’s listing on PyPI.

The Python Build Process

To run the build process tool, you use the command,

python -m build

But before you can do that, you need to install it

python -m pip install build

When you run the build command in a project that contains a pyproject.toml file, it will create new files and directories. These include the dist folder, which contains two files, a compressed archive file called sdist and a .whl file that you then distribute on PyPI.

How to Generate a Python Package?

To help you solidify what we have just learned, here is a walkthrough example of generating a Python package.

#1. Create an Example Project

To begin, create a simple package with the following folder structure

example_package/
├─ example_package/
│  ├─ example_module.py
│  ├─ __init__.py
├─ pyproject.toml
├─ setup.cfg
├─ README.md

The project root directory is called example_package. That is where our entire codebase is contained. Inside the project root, we have three files and a directory. Their contents are explained below:

pyproject.toml

This file contains information about what build tools to use when building your project. For this simple example, these are the contents:

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

In this case, we are declaring setuptools.build_meta as our build backend. But setuptools.build_meta is contained inside the setuptools package, so first, we list it as a requirement in our list of requirements. We will discuss more options you can specify later in this article.

README.md

Contains information about your package. This will be displayed as documentation on your package’s page on PyPI. You can write anything in that file.

setup.cfg

The setup.cfg file contains project metadata, such as the name of the package and the current version. For now, add the following code as the contents of setup.cfg:

[metadata]
name = example-package
version = 1.0.0

example-project

Contained within our root directory is another directory with the same name. This directory is where our source code resides. For demonstration purposes, I included two files:

  • example_module.py – This contains a dummy function. You can do the same as well.
  • __init__.py – It will make the directory a package that can be imported. It can be empty.

#2. Run the Build Command

Now, you can run the build command in the project root directory.

python -m build

If you have not, make sure you install the tool using the following:

pip install build

You should get an output that looks like this:

Screenshot-from-2023-06-01-01-05-54-1

As you can see, the last line tells you that it built example-package-1.0.0.tar.gz and example-package-1.0.0-py3-none-any-whl. When you list your directory contents using the ls command below, you should see new files.

ls

The output should be as follows:

dist  example_package  example_package.egg-info  pyproject.toml  README.md  setup.cfg
Screenshot-from-2023-06-01-01-27-15

If you list the contents of your dist directory, you should find the .whl file and the tar.gz file.

$ ls dist
example_package-1.0.0-py3-none-any.whl
example-package-1.0.0.tar.gz
Screenshot-from-2023-06-01-01-29-24

Contents of the pyproject.toml file

In our simple example, we only specified the build system of our Python project. However, you can add more information to your pyproject.toml file. These are some of the common options.

metadata

Instead of specifying metadata in the setup.cfg, you can write it in your pyproject.toml. This information will be used when creating a listing for your package on the package index.

In addition, you can specify the dependencies of your package and their versions so they can be installed when your package is installed.

[project]
name = "hello-world"
version = "1.0.0"
description = "My first Python package"
requires-python = ">=3.8"
keywords = ["python", "first-project"]
authors = [
    {name = "John Doe", email = "john@example.com"},
]
dependencies = [
    "requests",
    "gidgethub[httpx]>4.0.0",
]

tool.<tool_name>

You can also use tool.<tool_name> where <tool_name> is the name of the tool to provide different configuration options for the tools you use.

This can only be done with tools that support configuration using this method. For example, you could pass in configuration options to Black, a code linter.

[tool.black]
line-length = 88
target-version = ["py38", "py39"]

Example file

Putting together what we have learned, here is an example of a pyproject.toml file:

[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

[metadata]
name = "my-project"
version = "1.0.0"
description = "A sample project"
author = "Your Name"
author_email = "your.email@example.com"
license = "MIT"
keywords = ["sample", "project"]

[options]
python_requires = ">=3.6"

[tool.black]
line-length = 88
include = "\\.pyi?$"
exclude = '''
/(
  \.git
  | \.hg
  | \.mypy_cache
  | \.tox
  | \.venv
  | _build
  | buck-out
  | build
  | dist
)/
'''

[tool.blackd]
port = 45484
host = "localhost"

For more information, read this page.

Advantages of pyproject.toml

✅ It provides a standard way to manage dependencies for Python projects. The dependencies
and other relevant metadata of projects can be specified in a declarative manner.

✅ It also provides a way to specify other metadata in your projects, such as the authors, licence, and GitHub URL, among other helpful attributes.

✅ It fits in with different build systems, and switching build systems is easy.

Final Words

pyproject.toml is a useful standard that helps avoid the disadvantages of using setup.py. It is most useful when you are creating packages for distribution. For most new projects, you should use pyproject.toml instead of setup.py.

Next, check out how to check the Python version in Windows, Linux, and macOS.

Thanks to our Sponsors
More great readings on Development
Power Your Business
Some of the tools and services to help your business grow.
  • Invicti uses the Proof-Based Scanning™ to automatically verify the identified vulnerabilities and generate actionable results within just hours.
    Try Invicti
  • Web scraping, residential proxy, proxy manager, web unlocker, search engine crawler, and all you need to collect web data.
    Try Brightdata
  • Monday.com is an all-in-one work OS to help you manage projects, tasks, work, sales, CRM, operations, workflows, and more.
    Try Monday
  • Intruder is an online vulnerability scanner that finds cyber security weaknesses in your infrastructure, to avoid costly data breaches.
    Try Intruder