关于Python分发包构建工具与配置文件作用的疑问
Hey there! This is such a common confusion when diving into Python packaging—let’s break this down step by step so it makes sense.
First: The Two Key Players (They Work Together, Not Against Each Other!)
Let’s get this straight first:
- setuptools is your build backend: it’s the tool that actually knows how to take your code, metadata (like package name, version), and dependencies, and turn it into a distributable package.
- PyPA’s
buildis your build frontend: it’s a standardized tool that acts as a middleman. It reads your configuration to figure out which backend to use (in your case, setuptools), then handles the process of invoking that backend to generate your distribution archives (the.tar.gzsource archive and.whlwheel file).
They’re not alternatives—you need the frontend to trigger the backend in a modern, standardized way.
What Each File Does
Let’s break down the three files you’re seeing:
1. pyproject.toml
This is the "configuration glue" between the frontend and backend. Its main jobs are:
- Tell build tools (like
piporbuild) which backend to use for your project (here, setuptools). - Define the dependencies required just to build your package (like
setuptoolsandwheel).
Without this file, tools like build wouldn’t know how to process your project—they’d have to guess, which leads to inconsistencies. This is part of the modern Python packaging spec.
2. setup.cfg
This is where you put all your package’s metadata and build configuration in a declarative, static way. Instead of writing Python code in setup.py to define things like your package name, version, author, dependencies, or entry points, you list them here in a clean, INI-style format.
It’s the modern replacement for most of what used to be in setup.py—it’s easier to read, easier to maintain, and avoids running arbitrary code during the build process (which is safer).
3. setup.py
This is the legacy way to configure setuptools. Back in the day, you’d write Python code here to call setuptools.setup() with all your package details. Now, it’s mostly optional:
- You might still need it if you have dynamic configuration logic (like calculating the version from a Git tag at build time).
- For simple projects, you can even leave it as a tiny file that just calls
setuptools.setup()(since setuptools will automatically read fromsetup.cfg), or omit it entirely in newer setuptools versions.
Why the Tutorial Tells You to Use setuptools and Run py -m build
The tutorial isn’t contradicting itself! Here’s what’s happening:
- When you run
py -m build, you’re using the PyPA build frontend. - The frontend reads your
pyproject.toml, sees that you’ve specified setuptools as the backend, and then invokes setuptools (using yoursetup.cfg/setup.pyconfiguration) to build your distribution archives.
This is the modern, recommended way to build packages. Previously, people would run python setup.py sdist bdist_wheel directly, but that approach is now discouraged because it bypasses the standardized frontend and can lead to issues with dependency management during builds.
Your Guess: Let’s Correct It
You said: "setup.py基于setuptools,若使用该文件安装包,无需setup.cfg和pyproject.toml,只需执行py -m pip install .即可将包安装到本地机器。"
This is partially true, but not aligned with modern best practices:
- If you only have a
setup.py,pip install .will work (pip uses setuptools as the default backend if nopyproject.tomlis present). - However, skipping
pyproject.tomlmeans you’re relying on pip’s defaults, which might not match the versions of setuptools/wheel you need. It also makes your project incompatible with modern build tools likebuild. - Using
setup.cfginstead of embedding all config insetup.pyis better for readability and maintainability.
Quick Cheat Sheet: Which Files Do You Need?
- Modern, standard packaging (recommended):
pyproject.toml+setup.cfg(setup.py is optional unless you need dynamic logic) - Legacy packaging (not recommended): Just
setup.py(works, but not future-proof) - Building distribution archives with
build: Must havepyproject.toml(to specify the backend) + eithersetup.cfgorsetup.py(to provide package metadata)
内容的提问来源于stack exchange,提问作者YoavKlein

