文章来源:Python猫作者:豌豆花猫我遇到这样一个问题:我需要使用setuptools将一个项目打包成一个whl文件,然后在Windows/Linux操作系统上pip安装,但是有有些依赖库只能在Windows上使用(比如pywinauto、pywingui、pywinrm),那么问题来了,如何实现打包文件的兼容安装呢?从打包的角度来看,这个问题的关键是看setup.py和requirements.txt文件。关于Python的包构建分发和setup.py的使用,这里有一篇文章写的很好,推荐阅读。另外,关于Python依赖库(requirements.txt)的管理,本文对pip、pipreqs、pigar、pip-tools、pipdeptree等工具进行了详细对比,也推荐阅读。有一个比较笨的实现方法:维护两个requirements.txt文件,分别用于打包,然后分发到不同的操作系统使用。但是这样会比较麻烦:维护两个依赖文件和两个包文件本身就很费力,而且在生成过程中,每次都要重命名以区别它们(注意包名有一定的规范约束,随意更改的话它,pip可能不认识),维护成本会很高。事实上,在不同的操作系统上维护软件包的版本并不少见。如果您曾经关注过不同版本的Python库文件,您会注意到许多库针对不同的操作系统分发了不同的版本。比如下面是Numpy在不同操作系统上相同版本号的分布(https://pypi.org/simple/numpy/):可以看出它是基于macos、linux和win三种类型操作系统及其位数,分为5个版本。维护这么多版本肯定很麻烦,但这样的结果意味着Numpy官方认为分发不同系统版本利大于弊,是有办法实现的。回到我们的问题,是否有必要像Numpy那样尝试打包成多个操作系统定制的包?答案是否定的。主要原因:Numpy这样做是因为它进行科学计算。为了提高效率,将编译好的C扩展文件打包,使其不需要依赖环境中的libxxx-devel等库。如果你编译安装过Python,应该会有这样的印象,需要安装zlib-devel、openssl-devel、libffi-devel等系统依赖。但是我们之前的问题比较简单。不是编译依赖不同(系统层面),而是三方库依赖不同(项目层面)。另一个主要原因是Numpy打包的不同系统版本不能简单地用setuptools等Python库打包,必须借助标准镜像构建。比如manylinux版本的打包见Github(https://github.com/pypa/manyl...),需要使用官方的Docker镜像。对于我们的问题,显然不想做那么多麻烦。总之,根据前面的分析,如果要实现操作系统兼容的打包,维护多个依赖文件,使用不同的构建包的方法,维护多系统特定的包,这些方法是可行的,但不是很适用。如果没有新的办法,这是一种考虑,但是有没有别的办法呢?一直被这个问题困扰,但一直没有深入研究,直到无意中在loguru这个用来记录日志的库的setup.py中看到:查看著名的requests库文件,发现也可以这样写:两个例子都写在setup.py文件中。其实我们如果使用requirements.txt文件,也可以按照这种格式写,然后读入,这是什么神奇的写法呢?它基于PEP-508(以及相关但撤回或拒绝的PEP-390、PEP-426、PEP-459、PEP-496),创建于2015年11月,其主要目的是增强pip工具,例如能力寻找包裹。比较重要的部分和我们的问题有关,就是区分操作系统的标识。相关的是:有了这样的扩展支持,可以解决打包依赖时的兼容性问题。比如colorama库,如果我们只需要依赖win32系统,那么打包的时候可以指定:"colorama>=0.3.4;sys_platform=='win32'";如果我们不需要限制win32系统,但是在windows环境下都安装的话,可以写成“colorama>=0.3.4;platform_system=='Windows'”。终于,我们解决了本文开头的问题。这个问题可能比较小,解决也没什么大不了的。一个小技巧分享给大家。
