Skip to content

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.

distutils was deprecated in Python 3.10 and removed in Python 3.12. Projects still importing from distutils.core must migrate to a modern build backend configured through pyproject.toml.

Original workflow

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

from distutils.core import setup

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

Running python setup.py install copied modules to the target system. Running python setup.py sdist produced a source distribution archive.

Relationship to setuptools

setuptools 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.

Pros

  • Shipped in the Python standard library; no extra install required
  • Defined the universal baseline every packaging tool extended for two decades
  • Supported C extension compilation on all major platforms

Cons

  • No dependency resolution: could not declare or install transitive dependencies
  • Poor extensibility: custom build steps required subclassing undocumented internals
  • Brittle compiler handling: C extension flags were platform-dependent and hard to tune
  • Removed in Python 3.12; unavailable on any modern Python

The limitations were felt most acutely in scientific computing. NumPy had to override nearly all of distutils to support Fortran, C++, and Cython, producing a parallel fork (numpy.distutils) that became a long-running maintenance burden. NumPy has since migrated to meson-python.

Deprecation and Removal

PEP 632 (distutils deprecation) 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 must migrate to a modern build backend configured through pyproject.toml. Options include setuptools, hatchling, meson-python, and scikit-build-core.

Learn More

Last updated on