资讯专栏INFORMATION COLUMN

python wheel 包命名规则和 abi 兼容

妤锋シ / 1715人阅读

摘要:注意,本文内容基于。包的命名规定包的命名格式为。其中各个的意义和取值在中有规定标记了具体的实现。举为例,首先必须包含的是实现名和版本号,比如对应的是其次,需要包含构建时特定的选项。反之,则不存在。不过判断给定包的兼容的做法与此有些许差异。

注意,本文内容基于python 2。python 3的处理方式可能有所不同,有需要的读者可以自己了解一下。

wheel 包的命名规定

wheel 包的命名格式为 {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl
其中各个 tag 的意义和取值在 PEP425 中有规定:https://www.python.org/dev/pe...

python tag 标记了具体的 python 实现。其中:

py 无实现特定的拓展

cp CPython,也就是通常使用的 Python 实现

ip IronPython,跑在 Windows CLI 平台上的 Python 实现

pp PyPy,带 JIT 的 Python 实现

jy Jython,跑在 JVM 上的 Python 实现

举个例子,如果 wheel 包里面包含了 C 拓展,那么打包出来的 python tag 就是 cpxx,其中 xx 是具体的版本号,如 cp27.

platform tag 也好理解,就是系统 _ 架构。比如 linux_x86_64

最陌生的恐怕是之间的 abi tag,这正是本文讨论的主题。

abi 这东西,看不见摸不着。系统上的东西嘛,敲下个命令就知道是什么操作系统;架构虽然玄乎点,不过也就是那么几种;然而有多少人知道自己当前使用的平台遵循着怎样的 abi 标准?什么时候 abi 可以兼容,什么时候又不可以?

pip wheel 打包时,abi tag是怎么敲定的

Python 对此有另外一个 PEP:https://www.python.org/dev/pe...

如果 sysconfig 定义了 SOABI,那么就用 SOABI 的值。当然这是 Python 3 的事务,这里我自然不用管。如果没定义 SOABI,比如 Python 2,wheel 会生成一个类似的 abi tag。在 Python 的标准里,这个 abi 取决于打包时使用的 Python 实现。举 CPython 为例,首先必须包含的是实现名和版本号,比如 CPython2.7.9 对应的是 cp27.其次,需要包含构建 CPython 时特定的选项。具体来说,打包时会依次判断当前的 CPython 是否有下列的功能,如果有,加上对应的 flag:

--with-pydebug (flag: d )

--with-pymalloc (flag: m )

--with-wide-unicode (flag: u )

通常,我们看到的 abi tag 会是这样的 cp27mu,这是因为 --with-pymalloc 是默认开启的,而包管理中分发的 CPython 会加上 --with-wide-unicode 选项。

有趣的是,如果打包时没办法判断 abi 类型,生成的 abi tag 会是 none。而如果 Python 包是不依赖特定的 abi 的纯 Python 实现,生成的 abi tag 也是 none。在安装时,值为 none 的 abi tag 会享受特殊待遇。这个下文再说。

另外同样的 Python 代码打出来 abi tag 相同的包,不一定完全一样。以我的亲身经历举例,pycrypto 这个库,在打包的时候会判断 libgmp 是否存在,如果存在,就构建 _fastmath 这个库。如果打包平台上存在 libgmp,打出来的包就会包含 _fastmath。反之,则不存在。而这两种情形下打出来的包,名字是一模一样的。

如何判断给定 wheel 包是否能够安装

通常判断依赖的时候,需要看下是否符合最低版本。不过 pip 判断给定 wheel 包的 abi 兼容的做法与此有些许差异。pip 的做法是,计算出一个支持的 abi tag 集合,然后判断目标 abi tag 是否在这个集合里。这个计算过程跟在打包时是一样的。这意味着,打包拓展的 CPython 需要跟安装的机器上的 CPython 版本是一致的,否则就装不了。对于“永远的2.7”来说,这不是什么问题;不过如果用的是 Python 3,又不能控制具体的 CPython 版本,对于 C 拓展还是现场编译安装比较靠谱。

其实说了这么多,还不如跑一个脚本:
/usr/local/lib/python2.7/site-packages/pip/pep425tags.py

pip 会运行这个脚本来判断 wheel 包。所以你只要

from pip import pep425tags
print(pep425tags.get_supported())

就能报出该系统上支持的 wheel 包名字。

当然对于 abi tag 为 none 的包,它可以在任何一个 abi 版本上安装。因为所有的平台都至少支持 none abi。但如果一个平台上的 Python 如此古怪,以致于没办法确定它的 abi 类型,那么也就只能装上 abi tag 为 none 的包,即纯 Python 实现抑或同样古怪得无法判断打包时的 abi 的包。真是同类相聚啊。顺便一提,在 Ubuntu 14.04 和同期的系统,通过包管理安装的 pip 有一个已知 bug,有些时候无法正确判断 abi 类型,所以打出来的包的 tag 是 none,且任何带特定 abi 的包都装不上去。我们曾经遇到这个 bug,最后通过升级 pip 解决了。感兴趣的读者可以比较这包管理版本和最新版本,两个 pip 的 pep425tags.py 有什么异同。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44318.html

相关文章

  • 在 MaxCompute UDF 中运行 Scipy

    摘要:编写完成后,将代码保存为,并在中执行此后创建函数。执行创建后,便可以在中执行查询暂不支持,因而需禁用其他如果包依赖了其他包,需要一并上传并同时加入到依赖中。 摘要: 新版 MaxCompute Isolation Session 支持 Python UDF。也就是说,Python UDF 中已经可以跑二进制包。刚才以 Scipy 为例踩了一下坑,把相关的过程分享出来。 新版 MaxCo...

    kbyyd24 评论0 收藏0
  • 通过demo学习OpenStack开发所需的基础知识 -- 软件管理

    摘要:不幸的是,在软件包管理十分混乱,至少历史上十分混乱。的最大改进是将函数的参数单独放到一个的文件中这些成为包的元数据。基于的版本号管理。的版本推导这里重点说明一下基于的版本号管理这个功能。开发版本号的形式如下。 为什么写这个系列 OpenStack是目前我所知的最大最复杂的基于Python项目。整个OpenStack项目包含了数十个主要的子项目,每个子项目所用到的库也不尽相同。因此,对于...

    blastz 评论0 收藏0
  • Python Tips

    摘要:的三种数据类型字典列表元组,分别用花括号中括号小括号表示。约等于上句,可能是因为自定义变量名与内部函数或变量同名了。下,默认路径一般为。的日志模块中计时器定时器计划任务,。对象的问题怎样忽略警告不打印烦人的警告打印到终端同时记录到文件。 Python Enhancement Proposal。(PEP,Python增强建议书) Python之禅(import this) Pytho...

    Reducto 评论0 收藏0
  • Node.js 指南(ABI稳定性)

    摘要:确保兼容性的剩余责任在于团队维护头文件,这些头文件提供了在编译时在中保持稳定的。中的稳定性提供由几个独立团队维护的头文件,例如,团队维护诸如和之类的头文件。由团队维护,尽管与团队密切合作,但该团队是独立的,并且有自己的时间表和优先级。 ABI稳定性 介绍 应用程序二进制接口(ABI)是程序调用函数和使用其他编译程序的数据结构的一种方法,它是应用程序编程接口(API)的编译版本,换句话说...

    Simon_Zhou 评论0 收藏0

发表评论

0条评论

妤锋シ

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<