What’s the difference between setup.py and setup.cfg in python projects

Traditionally, setup.py has been used to build a Python package, i.e.,

python setup.py build

Like any old Python file, setup.py can contain lots of code. In most cases, however, it is purely declarative and simply lists package properties, e.g.,

from setuptools import setup

setup(
    name="foobar",
    version="0.1.0",
    author="John Doe",
    # ...
)

In fact, some consider it bad style to put much logic in setup.py. To reflect that, setup.cfg (which is declarative by design) has become more popular for packaging:

[metadata]
name = foobar
version = 0.1.0
author = John Doe
# ...

This has the advantage that the packaging software (e.g., setuptools) doesn’t need to evaluate a Python file to get the meta data, but can simply parse a config file.

You can add a dummy setup.py to that,

from setuptools import setup

if __name__ == "__main__":
    setup()

or go full PEP 517/518 and instead add a pyproject.toml.

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

You can then build your projects using pypa-build (pip install build) with

python3 -m build --sdist --wheel .

Since 2020 pyproject.toml can contain metadata too, so you don’t need setup.cfg anymore. The data layout looks more or less like setup.cfg but follows the standardized TOML format:

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

[project]
name = "foobar"
version = "0.1.0"
authors = [{name = "John Doe", email = "john@doe.com"}]
# [...]

One design goal is that multiple build systems will support it (setuptools, flit, Poetry, …). As of 2022, setuptools will still give you an “experimental” warning when installing that package, but that might go away soon.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)