如何使基于 setup.py 的项目现代化?#

是否应该添加 pyproject.toml#

强烈建议使用 pyproject.toml 文件。本身存在 pyproject.toml 文件并没有多大用处。 [1] 实际上强烈建议使用 pyproject.toml 中的 [build-system] 表。

是否应该删除 setup.py#

不,setup.py 可以存在于基于 Setuptools 的现代项目中。 setup.py 文件是 setuptools 的有效配置文件,碰巧是用 Python 编写的。但是,以下命令已弃用,不得再运行,而应改用推荐的替换命令

已弃用

建议

python setup.py install

python -m pip install .

python setup.py develop

python -m pip install --editable .

python setup.py sdist

python -m build

python setup.py bdist_wheel

了解更多详情

从哪里开始?#

项目 必须在其源树的根目录中包含一个 pyproject.toml 文件,其中包含一个 [build-system] 表,如下所示

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

这是让 构建前端 知道 Setuptools 是此项目的 构建后端 的标准化方法。

请注意,存在 pyproject.toml 文件(即使为空)也会触发 pip 更改其默认行为以使用构建隔离

了解更多详情

如何处理额外的构建时依赖项?#

除了 setuptools 本身之外,如果 setup.py 依赖于其他第三方库(不在 Python 标准库中),则必须将这些库列在 requires[build-system] 表,以便构建前端知道在构建 分发 时安装这些库。

例如,一个 setup.py 文件如下所示

import setuptools
import some_build_toolkit  # comes from the `some-build-toolkit` library

def get_version():
    version = some_build_toolkit.compute_version()
    return version

setuptools.setup(
    name="my-project",
    version=get_version(),
)

需要一个类似这样的 pyproject.toml 文件(setup.py 保持不变)

[build-system]
requires = [
    "setuptools",
    "some-build-toolkit",
]
build-backend = "setuptools.build_meta"

了解更多详情

构建隔离功能是什么?#

构建前端通常会创建一个临时虚拟环境,其中仅安装 build-system.requires 中列出的构建依赖项(及其依赖项),并在该环境中触发构建。

对于某些项目,这种隔离是不需要的,可以按如下方式停用

  • python -m build --no-isolation

  • python -m pip install --no-build-isolation

了解更多详情

如何处理打包元数据?#

所有静态元数据都可以选择移动到 [project] 表中 pyproject.toml

例如,一个 setup.py 文件如下所示

import setuptools

setuptools.setup(
    name="my-project",
    version="1.2.3",
)

可以完全替换为类似这样的 pyproject.toml 文件

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

[project]
name = "my-project"
version = "1.2.3"

阅读 声明项目元数据:[project] 表 以了解 [project] 表中允许的内容的完整规范。

如何处理动态元数据?#

如果某些打包元数据字段不是静态的,则需要将它们列为 dynamic 在此 [project] 表中。

例如,一个 setup.py 文件如下所示

import setuptools
import some_build_toolkit

def get_version():
    version = some_build_toolkit.compute_version()
    return version

setuptools.setup(
    name="my-project",
    version=get_version(),
)

可以按如下方式进行现代化

[build-system]
requires = [
    "setuptools",
    "some-build-toolkit",
]
build-backend = "setuptools.build_meta"

[project]
name = "my-project"
dynamic = ["version"]
import setuptools
import some_build_toolkit

def get_version():
    version = some_build_toolkit.compute_version()
    return version

setuptools.setup(
    version=get_version(),
)

了解更多详情

如果无法更改的内容需要 setup.py 文件怎么办?#

例如,存在一个无法轻松更改的进程,它需要执行诸如 python setup.py --name 的命令。

即使其所有内容都已移至 pyproject.toml,在项目源代码树中保留 setup.py 文件也是完全可以的。此文件可以像下面这样极简

import setuptools

setuptools.setup()

在哪里可以阅读更多关于此内容的信息?#