放弃对旧版 Python 的支持

Dropping support for older Python versions

通过标准的 核心元数据 1.2 规范中的 “Requires-Python” 属性,可以实现停止支持旧版 Python 的功能。

像 Pip 这样的 Metadata 1.2+ 安装工具将会依据此规范,通过匹配当前的 Python 运行环境并与包元数据中的要求版本进行比较。如果不匹配,它会尝试安装最后一个支持该 Python 版本的包分发版本。

此机制可以通过在包元数据中修改 Requires-Python 属性来停止对旧版 Python 的支持。

The ability to drop support for older Python versions is enabled by the standard 核心元数据规范 1.2 specification via the "Requires-Python" attribute.

Metadata 1.2+ installers, such as Pip, will adhere to this specification by matching the current Python runtime and comparing it with the required version in the package metadata. If they do not match, it will attempt to install the last package distribution that supported that Python runtime.

This mechanism can be used to drop support for older Python versions, by amending the Requires-Python attribute in the package metadata.

要求

Requirements

此工作流要求安装包的用户使用 Pip [1] 或其他支持 Metadata 1.2 规范的安装工具。

This workflow requires that the user installing the package uses Pip [2], or another installer that supports the Metadata 1.2 specification.

处理通用轮子

Dealing with the universal wheels

传统上,提供与 Python 2 和 Python 3 语义兼容的 Python 代码的 Setuptools 项目,会生成在名称中带有 py2.py3 标签的 wheels。在放弃对 Python 2 的支持时,重要的是不要忘记将这个标签更改为仅 py3。这个配置通常在 setup.cfg 文件的 [bdist_wheel] 部分中,通过设置 universal = 1 来完成。

如果你使用此方法,应该移除该选项或部分,或者显式将 universal 设置为 0

# setup.cfg

[bdist_wheel]
universal = 0  # Make the generated wheels have "py3" tag

提示

关于 deprecated 直接调用 setup.py,在命令行中传递 --universal 标志可能会覆盖此设置。

Traditionally, Setuptools projects providing Python code that is semantically compatible with both Python 2 and Python 3, produce wheels that have a py2.py3 tag in their names. When dropping support for Python 2, it is important not to forget to change this tag to just py3. It is often configured within setup.cfg under the [bdist_wheel] section by setting universal = 1.

If you use this method, either remove this option or section, or explicitly set universal to 0:

# setup.cfg

[bdist_wheel]
universal = 0  # Make the generated wheels have "py3" tag

提示

Regarding deprecated direct setup.py invocations, passing the --universal flag on the command line could override this setting.

定义所需的 Python 版本

Defining the Python version required

1. 安装 twine

1. Install twine

确保你安装了最新版本的 twine。 步骤:

python3 -m pip install --upgrade twine
py -m pip install --upgrade twine

Ensure that you have twine available at its latest version. Steps:

python3 -m pip install --upgrade twine
py -m pip install --upgrade twine

2. 指定受支持的 Python 发行版的版本范围

2. Specify the version ranges for supported Python distributions

在你的项目的 pyproject.toml 文件中设置声明支持哪些 Python 版本范围。 requires-python 配置字段对应于 Requires-Python 核心元数据字段:

[build-system]
...

[project]
requires-python = ">= 3.8" # 至少需要 Python 3.8

你可以指定版本范围和排除规则(遵循 版本标识符 规范),例如至少 Python 3.9,或者至少 Python 3.7 及以后的版本,但跳过 3.7.0 和 3.7.1 这两个小版本:

requires-python = ">= 3.9"
requires-python = ">= 3.7, != 3.7.0, != 3.7.1"

如果使用 Setuptools 构建后端,请参阅 dependency-management 文档了解更多选项。

小心

避免在版本范围中添加上限,例如 ">= 3.8, < 3.10"。这样做可能会导致不同的错误和版本冲突。有关更多信息,请参阅 discourse-discussion

Set the version ranges declaring which Python distributions are supported within your project's pyproject.toml. The requires-python configuration field corresponds to the Requires-Python core metadata field:

[build-system]
...

[project]
requires-python = ">= 3.8" # At least Python 3.8

You can specify version ranges and exclusion rules (complying with the 版本标识符 specification), such as at least Python 3.9. Or, at least Python 3.7 and beyond, skipping the 3.7.0 and 3.7.1 point releases:

requires-python = ">= 3.9"
requires-python = ">= 3.7, != 3.7.0, != 3.7.1"

If using the Setuptools build backend, consult the dependency-management documentation for more options.

小心

Avoid adding upper bounds to the version ranges, e. g. ">= 3.8, < 3.10". Doing so can cause different errors and version conflicts. See the discourse-discussion for more information.

3. 发布前验证元数据

3. Validating the Metadata before publishing

在 Python 源代码包(即你下载的 zip 或 tar-gz 文件)中,有一个名为 PKG-INFO 的文本文件。

此文件由 build backend 在生成源代码包时生成。文件包含一组键值对,键的列表是 PyPA 标准元数据格式的一部分。

你可以通过以下命令查看生成的文件内容:

tar xfO dist/my-package-1.0.0.tar.gz my-package-1.0.0/PKG-INFO

在发布包之前,请验证以下内容是否就绪:

  • 如果已正确升级, Metadata-Version 的值应为 1.2 或更高版本。

  • Requires-Python 字段已设置,并与配置文件中的规范相匹配。

Within a Python source package (the zip or the tar-gz file you download) is a text file called PKG-INFO.

This file is generated by the build backend when it generates the source package. The file contains a set of keys and values, the list of keys is part of the PyPA standard metadata format.

You can see the contents of the generated file like this:

tar xfO dist/my-package-1.0.0.tar.gz my-package-1.0.0/PKG-INFO

Validate that the following is in place, before publishing the package:

  • If you have upgraded correctly, the Metadata-Version value should be 1.2 or higher.

  • The Requires-Python field is set and matches your specification in the configuration file.

4. 发布包

4. Publishing the package

按照 将您的项目上传到 PyPI 中的建议进行操作。

Proceed as suggested in 将您的项目上传到 PyPI.

放弃 Python 版本

Dropping a Python version

原则上,至少应该尽可能长时间保留对 Python 版本的元数据支持,因为一旦删除了对某个版本的支持,仍然依赖该版本的用户将被迫降级。然而,如果支持特定版本成为新功能的阻碍,或者出现其他问题,则应修改元数据中的 Requires-Python 字段。当然,这也取决于项目是否需要保持稳定并覆盖更广泛的用户群体。

每次版本兼容性的变更应该有自己的发布版本。

提示

在放弃支持某个 Python 版本时,除了更新可见位置(如测试环境)中使用的版本外,通常也值得升级项目的代码语法。像 pyupgraderuff 这样的工具可以自动化一些工作。

In principle, at least metadata support for Python versions should be kept as long as possible, because once that has been dropped, people still depending on a version will be forced to downgrade. If however supporting a specific version becomes a blocker for a new feature or other issues occur, the metadata Requires-Python should be amended. Of course this also depends on whether the project needs to be stable and well-covered for a wider range of users.

Each version compatibility change should have its own release.

小技巧

When dropping a Python version, it might also be rewarding to upgrade the project's code syntax generally, apart from updating the versions used in visible places (like the testing environment). Tools like pyupgrade or ruff can automate some of this work.