如何使基于 setup.py
的项目现代化?¶
How to modernize a setup.py
based project?
是否应添加 pyproject.toml
?¶
Should pyproject.toml
be added?
强烈推荐使用 pyproject.toml 文件。
文件本身的存在并没有太大意义。[1]
真正强烈推荐的是在 pyproject.toml
中的 [build-system]
表。
A pyproject.toml file is strongly recommended.
The presence of a pyproject.toml
file itself does not bring much. [2]
What is actually strongly recommended is the [build-system]
table in pyproject.toml
.
是否应删除 setup.py
?¶
Should ``setup.py`` be deleted?
不用删除,现代基于 Setuptools 的项目中可以存在 setup.py
文件。
setup.py
文件是一个有效的 setuptools 配置文件,虽然它是用 Python 编写的。
但是,以下命令已经被弃用,不得再运行,应使用它们推荐的替代命令:
弃用命令 |
推荐命令 |
---|---|
|
|
|
|
|
|
|
更多详情:
No, setup.py
can exist in a modern Setuptools based project.
The setup.py file is a valid configuration file for setuptools
that happens to be written in Python.
However, the following commands are deprecated and MUST NOT be run anymore,
and their recommended replacement commands should be used instead:
Deprecated |
Recommendation |
---|---|
|
|
|
|
|
|
|
For more details:
从哪里开始?¶
Where to start?
项目必须在其源代码树的根目录下包含一个 pyproject.toml
文件,并且该文件必须包含一个类似如下的 [build-system]
表:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
这是让 构建前端 知道 Setuptools 是该项目的 构建后端 的标准化方法。
请注意,存在 pyproject.toml
文件(即使文件为空)会触发 pip 改变其默认行为,使用 构建隔离。
更多详情:
The project must contain a pyproject.toml
file at the root of its source tree
that contains a [build-system]
table like so:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
This is the standardized method of letting build frontends know that Setuptools is the build backend for this project.
Note that the presence of a pyproject.toml
file (even if empty)
triggers pip to change its default behavior to use build isolation.
For more details:
如何处理额外的构建时依赖项?¶
How to handle additional build-time dependencies?
除了 setuptools 本身,如果 setup.py
依赖于其他第三方库(不包括 Python 标准库中的库),这些库必须在 [build-system]
表的 requires
列表中列出,以便构建前端在构建 分发包 时知道安装它们。
例如,像这样的 setup.py
文件:
import setuptools
import some_build_toolkit # 来自 `some-build-toolkit` 库
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"
更多详情:
On top of setuptools itself,
if setup.py
depends on other third-party libraries (outside of Python's standard library),
those must be listed in the requires
list of the [build-system]
table,
so that the build frontend knows to install them
when building the distributions.
For example, a setup.py
file such as this:
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(),
)
requires a pyproject.toml
file like this (setup.py
stays unchanged):
[build-system]
requires = [
"setuptools",
"some-build-toolkit",
]
build-backend = "setuptools.build_meta"
For more details:
什么是构建隔离功能?¶
What is the build isolation feature?
构建前端通常会创建一个临时的虚拟环境,在该环境中只安装 build-system.requires
下列出的构建依赖(以及它们的依赖),并在该环境中触发构建。
对于某些项目,这种隔离是不希望的,可以通过以下方式禁用:
python -m build --no-isolation
python -m pip install --no-build-isolation
更多详情:
Build frontends typically create an ephemeral virtual environment
where they install only the build dependencies (and their dependencies)
that are listed under build-system.requires
and trigger the build in that environment.
For some projects this isolation is unwanted and it can be deactivated as follows:
python -m build --no-isolation
python -m pip install --no-build-isolation
For more details:
如何处理打包元数据?¶
How to handle packaging metadata?
所有静态元数据可以选择性地移动到 pyproject.toml
文件中的 [project]
表中。
例如,一个如下所示的 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]
表中允许的内容的完整规范。
All static metadata can optionally be moved to a [project]
table in pyproject.toml
.
For example, a setup.py
file such as this:
import setuptools
setuptools.setup(
name="my-project",
version="1.2.3",
)
can be entirely replaced by a pyproject.toml
file like this:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "my-project"
version = "1.2.3"
Read 声明项目元数据:[project] 表 for the full specification of the content allowed in the [project]
table.
如何处理动态元数据?¶
How to handle dynamic metadata?
如果某些打包元数据字段不是静态的,
则需要在 [project]
表中将其列为 dynamic
。
例如,一个如下所示的 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(),
)
更多细节请参阅:
If some packaging metadata fields are not static
they need to be listed as dynamic
in this [project]
table.
For example, a setup.py
file such as this:
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(),
)
can be modernized as follows:
[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(),
)
For more details:
如果某些无法更改的内容需要 setup.py
文件怎么办?¶
What if something that can not be changed expects a setup.py
file?
例如,某些过程可能无法轻易更改,
并且需要执行类似 python setup.py --name
的命令。
即使所有内容已被移至 pyproject.toml
,
在项目源代码树中保留 setup.py
文件也是完全可以的。
这个文件可以简化为如下形式:
import setuptools
setuptools.setup()
For example, a process exists that can not be changed easily
and it needs to execute a command such as python setup.py --name
.
It is perfectly fine to leave a setup.py
file in the project source tree
even after all its content has been moved to pyproject.toml
.
This file can be as minimalistic as this:
import setuptools
setuptools.setup()
在哪里可以阅读更多相关信息?¶
Where to read more about this?