As Python developers, we often work with configurations, dependencies, and various settings to manage our projects. One key file that has become central to this is pyproject.toml. Introduced as part of PEP 518, pyproject.toml is a standardized configuration file for Python projects. It’s designed to simplify packaging, dependency management, and integration with modern Python tools like pip, poetry, black, and tox. If you’re not yet familiar with it, this article will break down the purpose, syntax, and uses of pyproject.toml, along with a number of practical examples to get you started.
What is pyproject.toml?
At its core, pyproject.toml is a TOML (Tom’s Obvious, Minimal Language) file that holds configuration information for various tools involved in Python project management. The goal is to provide a unified format for tool configuration, allowing developers to keep project-related settings in one place.
With the increasing complexity of Python projects and the rise of various tools for testing, linting, packaging, and more, the Python Packaging Authority (PyPa) introduced pyproject.toml to unify and streamline this process.
Structure of pyproject.toml
A pyproject.toml file typically consists of sections, each serving a different purpose. Let’s take a look at a general structure:
Structure of pyproject.toml
A pyproject.toml file typically consists of sections, each serving a different purpose. Let’s take a look at a general structure:
[tool]
[tool.black]
line-length = 88
[tool.poetry]
name = "my-project"
version = "0.1.0"
description = "A description of my project"
authors = ["John Doe <john@example.com>"]
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"
- [tool]: This section includes various tool configurations (e.g.,
black,poetry,pytest, etc.). - [build-system]: This section specifies build requirements for your project. It includes tools like
setuptoolsorflitthat are necessary for building the project.
Key Sections and Their Uses
- [build-system]: The build system section is required by PEP 518 and is vital for defining the tool used to build the package, along with its dependencies. If you’re using
setuptoolsorflit, you need this section. It also defines which version ofsetuptoolsis required.
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
This section makes sure that pip installs the right tools before the project can be built, avoiding errors related to missing dependencies.
- [tool]: This is the most commonly used section. It holds configurations for various tools. Some popular tools that make use of
pyproject.tomlinclude:
- black: For automatic code formatting.
- poetry: For dependency management and packaging.
- pytest: For testing configurations.
- tox: For multi-environment testing.
Each of these tools has its own configuration sub-section within [tool].
Configuring Black
black is a popular Python code formatter. Here’s how you can configure it inside pyproject.toml:
[tool.black]
line-length = 88
target-version = ['py39']
skip-string-normalization = true
line-length: Defines the maximum number of characters per line. The default is 88, but you can change this to match your team’s preferences.target-version: Specifies the Python versions to support.skip-string-normalization: When set totrue, this preventsblackfrom changing string quotes (single to double or vice versa).
Configuring Poetry for Dependency Management
poetry is a powerful tool for managing dependencies and packaging Python projects. You can define your project’s dependencies, version, description, and other metadata in the pyproject.toml under the [tool.poetry] section.
[tool.poetry]
name = "my-project"
version = "0.1.0"
description = "A description of my project"
authors = ["John Doe <john@example.com>"]
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.25"
[tool.poetry.dev-dependencies]
pytest = "^6.0"
- name and version: Define the project’s name and version.
- dependencies: Lists the project’s runtime dependencies. The
^indicates a compatible version (e.g.,^2.25means any version ofrequeststhat is compatible with2.25). - dev-dependencies: These are dependencies required for development but not for production, such as testing libraries.
Configuring Pytest
pytest is another popular tool for running tests in Python. You can configure it directly in pyproject.toml as follows:
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-v"
testpaths: Specifies wherepytestshould look for tests.addopts: Additional options to pass topytestwhen running it.
Tips and Tricks for Working with pyproject.toml
1. Keep it Clean and Simple
While it might be tempting to overload your pyproject.toml with settings for every tool you use, it’s best to keep the configuration lean. Stick to essential settings to avoid clutter.
2. Use [build-system] for Compatibility
If you’re building a Python package and using tools like setuptools or flit, ensure that the [build-system] section is present and properly configured. This ensures that your project builds correctly across different environments.
3. Centralize Your Configuration
Rather than having configuration files spread across your project (e.g., .flake8, tox.ini, pytest.ini), consider consolidating them into pyproject.toml. Many modern tools support this, making it easier to manage.
4. Version Constraints
In pyproject.toml, it’s common to specify version constraints for dependencies. Understanding the difference between version specifiers like ^, ~, >=, and == will help prevent issues down the line:
^means compatible with the given version (e.g.,^2.25allows2.xbut not3.0).~allows minor version updates (e.g.,~1.2allows any version between1.2and2.0).>=means greater than or equal to the specified version.==means exactly this version.
5. Customize Your Linting and Formatting Tools
With tools like black, flake8, and pylint configured via pyproject.toml, you can fine-tune your code style to match your team’s preferences. Don’t hesitate to experiment with different settings like line length or string normalization to improve your code quality.
6. Tool-Specific Configuration
Every tool has its own set of configuration options. Always refer to the official documentation of tools like black, poetry, and pytest for specific configurations. Tools like black are designed to work out of the box, but some fine-tuning (e.g., disabling certain rules) can make your workflow smoother.
Conclusion
In summary, pyproject.toml is an indispensable file for modern Python development. It provides a centralized, standardized way to configure various Python tools, making it easier to manage dependencies, packaging, and other project settings. Whether you’re using black for formatting, poetry for dependency management, or pytest for testing, pyproject.toml allows you to keep your project configurations in one place, streamlining your workflow.
By leveraging the full potential of pyproject.toml, you’ll find that your Python projects become easier to maintain, more portable, and better aligned with best practices. So, whether you’re starting a new project or improving an existing one, consider embracing pyproject.toml as your go-to configuration file!

