防止软件包安装在旧 Python 版本上

Prevent package from being installed on old Python versions

我们可以在 setup.py 文件中放入什么来防止 pip 在使用不受支持的 Python 版本时收集和尝试安装软件包?

例如 magicstack 是一个使用 trove 分类器列出的项目:

Programming Language :: Python :: 3 :: Only

因此,如果 pip --version 绑定到 python 2.7,我预计会出现以下行为:

$ pip install magicstack
Collecting magicstack
  Could not find a version that satisfies the requirement magicstack (from versions: )
No matching distribution found for magicstack

但实际行为是 pip 收集一个版本,下载它,尝试安装它,但失败了。还有其他 Python3-only 版本,例如 curio,实际上安装得很好 - 因为 setup.py 没有使用任何 Python 3 特定 - 只是在使用某些 Python 3 only 语法时的导入时间。而且我确定有些软件包安装正常,导入正常,并且可能只在运行时失败!

以 pip 将尊重的方式指定支持的 Python 版本的正确方法是什么? 我找到了一个解决方法,涉及只上传一个轮子文件,并拒绝上传 .tar.gz 分发版,但我很想知道正确的修复方法。


编辑:如果Python/os/architecture不匹配,pip如何知道下载轮子分布?它只是使用 .whl filename convention 还是有比幕后发生的更复杂的事情?我们能否以某种方式将元数据提供给源分发,让 pip 正确处理 .tar.gz 上传?

pypi 上的 magicstack 发行版已损坏。它失败了,因为源分发不包含 magicstack 包,即使源分发的 setup.py 说它应该包含。

只要 pypi 包含源分发版(例如 .tar.gz.zip),如果 pip 找不到匹配的二进制分发版(例如 .egg.egg.whl) 适用于您的 python/os/architecture 版本。

一种选择是只将二进制发行版上传到 PyPI(最好是 wheels)。另一种选择是检查 setup.py 中的 sys.version 是否兼容版本,否则引发异常。

有一个正确的方法可以做到这一点,但不幸的是 pip 仅在 9.0.0 版本(2016-11-02 发布)中才开始支持它,因此使用旧版本 pip 的用户将继续下载软件包 willy-不管他们的 Python 版本是什么。

在您的 setup.py 文件中,传递 setup() 一个 python_requires 参数,将您的软件包支持的 Python 版本列为 PEP 440 version specifier。例如,如果您的包裹仅适用于 Python 3+,请写:

setup(
    ...
    python_requires='>=3',
    ...
)

如果您的软件包适用于 Python 3.3 及更高版本,但您还不愿意承诺 Python 4 支持,请写:

setup(
    ...
    python_requires='~=3.3',
    ...
)

如果您的软件包适用于 Python 2.6、2.7 和 Python 3 从 3.3 开始的所有版本,请写:

setup(
    ...
    python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4',
    ...
)

以此类推

完成后,您需要将 setuptools 版本至少升级到 24.2.0,以便处理 python_requires 参数;早期版本只会忽略它并发出警告。随后构建的所有项目的 sdists 和 wheels 将包含相关的元数据,这些元数据告诉 PyPI 告诉 pip 它们适用的 Python 版本。