防止软件包安装在旧的 Python 版本上
Posted
技术标签:
【中文标题】防止软件包安装在旧的 Python 版本上【英文标题】:Prevent package from being installed on old Python versions 【发布时间】:2017-07-03 11:17:56 【问题描述】:当使用不受支持的 Python 版本时,我们可以在 setup.py
文件中添加什么来防止 pip 收集和尝试安装包?
例如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 的版本,例如 curio
,它们实际上安装得很好 - 因为 setup.py
没有使用任何 Python 3 特定的东西 - 只有在使用某些 Python 3 语法时才会在导入时失败。而且我确定有些软件包可以安装,导入正常,并且可能只会在运行时失败!
以 pip 尊重的方式指定支持的 Python 版本的正确方法是什么?我找到了一种解决方法,包括只上传一个 wheel 文件,并拒绝上传 .tar .gz 发行版,但我很想知道正确的修复方法。
编辑: 如果 Python/os/architecture 不匹配,pip 如何知道 不 下载***分发?它只是使用.whl filename convention 还是有比幕后发生的更复杂的事情?我们能否以某种方式将元数据提供给源分发,以使 pip 对 .tar.gz 上传做正确的事情?
【问题讨论】:
我不知道这是 正确的 答案...但是如果magicstack
是 python3 只是因为 setup.py
在 python2.x 上失败,那么它似乎像使这项工作的一种可能方法是强制您的 setup.py
在不适当的 python 版本上失败...
哈奇。如果 pip 绑定到不受支持的 Python 解释器,我根本不希望收集或下载包,更不用说通过执行 setup.py
尝试安装了。
Google 找到了一些 previous questions 并回答说让你的 setup.py
检查 Python 版本。
相关:packaging.python.org/guides/…,其中提到“虽然分类器列表通常用于声明项目支持的 Python 版本,但此信息仅用于在 PyPI 上搜索和浏览项目,不适用于安装项目。要实际限制可以安装项目的 Python 版本,请使用 python_requires 参数。"
相关:***.com/a/64386359/1959808
【参考方案1】:
pypi 上的magicstack
分布已损坏。它失败了,因为源代码分发不包含 magicstack
包,即使源代码分发的 setup.py
说它应该包含。
只要 pypi 包含源代码分发版(例如 .tar.gz
、.zip
),pip 会在找不到匹配的二进制分发版(例如 .egg
、.whl
)时下载您的版本蟒蛇/操作系统/架构。
一种选择是仅将二进制分发版上传到 PyPI(最好是 wheels
)。另一种选择是检查setup.py
中的sys.version
以获取兼容版本,否则会引发异常。
【讨论】:
【参考方案2】:有一个正确的方法可以做到这一点,但不幸的是 pip 仅在 9.0.0 版本(2016-11-02 发布)中开始支持它,因此使用旧版本 pip 的用户将继续下载软件包,不管怎样它们适用于哪个 Python 版本。
在您的setup.py
文件中,传递setup()
一个python_requires
参数,该参数将您的包支持的Python 版本列为PEP 440version specifier。例如,如果您的包仅适用于 Python 3+,请编写:
setup(
...
python_requires='>=3',
...
)
如果您的包适用于 Python 3.3 及更高版本,但您还不愿意承诺支持 Python 4,请写:
setup(
...
python_requires='~=3.3',
...
)
如果您的包适用于 Python 2.6、2.7 以及从 3.3 开始的所有 Python 3 版本,请编写:
setup(
...
python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4',
...
)
等等。
完成此操作后,您需要将 setuptools 版本至少升级到 24.2.0,以便处理 python_requires
参数;早期版本只会忽略它并发出警告。之后构建的所有项目的 sdists 和***将包含相关的元数据,告诉 PyPI 告诉 pip 它们适用于哪些 Python 版本。
【讨论】:
@wim:python_requires
使用了什么版本说明符?
我已经上传了一个source distribution 用于在 pypi 上进行测试(请参阅here 以了解实现),它似乎正如您在 pypi 上所描述的那样工作。我只能在不同的索引上重现不正确的行为。我可能在devpi server 中遇到了一个错误,明天将进行更多调查...
查看这里了解更多有用信息:python3statement.org/practicalities
我的问题确实是由于索引中的错误(旧版本的 devpi 服务器无法正确提供 python_requires
元数据 - 我相信它在当前版本中已解决)。
我认为值得一提的是,该项目必须使用pip3 install [-e]
安装(而不是“直接”使用python3 setup.py install
),如下所述:python3statement.org/practicalities以上是关于防止软件包安装在旧的 Python 版本上的主要内容,如果未能解决你的问题,请参考以下文章
在旧版 OS X 上的 OS X10.6.4 上开发的软件包的兼容性问题
API 是不是应该在 API 响应中发回 UI 层文本/数据以允许在旧的 android/ios 应用程序版本中随时更改?