# distutils: Python's Original Build System

distutils was a standard library module that provided the original mechanism for building and distributing Python packages. It defined the `setup.py`-based workflow that became the foundation of Python packaging for over two decades.

## What It Did

distutils handled package building, installation, and distribution through a `setup.py` script:

```python
from distutils.core import setup

setup(
    name="example",
    version="1.0",
    py_modules=["example"],
)
```

Running `python setup.py install` would copy modules into the correct location on the target system. Running `python setup.py sdist` would produce a source distribution archive.

## Limitations

distutils worked for simple packages but struggled with anything beyond the basics:

- No dependency resolution. It could not declare or install package dependencies.
- Poor extensibility. Adding custom build steps required subclassing internal commands with minimal documentation.
- Opaque compiler handling. Configuring compiler flags for C extensions was brittle and platform-dependent.

These gaps were felt most acutely in scientific computing. NumPy had to override nearly all of distutils to support Fortran compilers, C++ compilation, Cython integration, and cross-platform build configurations. That fork, `numpy.distutils`, became a parallel maintenance burden for years.

## Relationship to setuptools

[setuptools](https://pydevtools.com/handbook/reference/setuptools.md) was created as a direct extension of distutils, adding dependency declaration (`install_requires`), automatic package discovery, entry points, and egg/wheel distribution formats. For most of its history, setuptools monkey-patched distutils at import time to layer these features on top.

## Deprecation and Removal

[PEP](https://pydevtools.com/handbook/explanation/pep.md) 632 deprecated distutils in Python 3.10 and scheduled its removal. Python 3.12 completed that removal.

Projects that relied on `from distutils.core import setup` or `distutils.core.Extension` need to migrate to a modern [build backend](https://pydevtools.com/handbook/explanation/what-is-a-build-backend.md) configured through [pyproject.toml](https://pydevtools.com/handbook/reference/pyproject.toml.md). Options include [setuptools](https://pydevtools.com/handbook/reference/setuptools.md), hatchling, meson-python, and scikit-build-core.

## Learn More

- [PEP 632: Deprecate distutils module](https://peps.python.org/pep-0632/)
- [Python 3.11 distutils documentation](https://docs.python.org/3.11/library/distutils.html) (last version with distutils)
- [Migrating from distutils](https://setuptools.pypa.io/en/latest/deprecated/distutils-legacy.html)
