Python 小技巧:如何实现操作系统兼容性打包?

简介: Numpy 这么做是因为它是做科学计算的,为了提升效率,它把编译好的 C 拓展文件打包,从而不需要依赖环境上的 libxxx-devel 之类的库。如果你编译安装过 Python,应该有印象需要安装 zlib-devel、openssl-devel 和 libffi-devel 之类的系统依赖。但我们前面的问题比较简单,并不是有不同的编译依赖(系统级),而只是三方库依赖不同(项目级)。另一个主要的原因,Numpy 打包出的不同系统版本,并非简简单单地用 setuptools 之类的 Python 库就能打包,而是要借助标准的镜像进行构建。

有一个这样的问题:现要用 setuptools 把一个项目打包成 whl 文件,然后 pip install 在 Windows/Linux 两种操作系统上,但是该项目中有一些依赖库只有 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 在不同操作系统上的分发版(pypi.org/simple/nump…):

22da741970fed0538c9762880815cea.png

可以看出它根据 macos、linux 和 win 三类操作系统及其位数,分成了 5 个版本。维护这么多版本,肯定是一件麻烦事,但是出现了这样的结果,就意味着 Numpy 官方认为分发不同系统版本是利大于弊的,而且是有办法实现的。

回到我们的问题,是否有必要像 Numpy 那样设法打包成多个操作系统定制的包呢?

答案是否定的。主要的原因:

  • Numpy 这么做是因为它是做科学计算的,为了提升效率,它把编译好的 C 拓展文件打包,从而不需要依赖环境上的 libxxx-devel 之类的库。如果你编译安装过 Python,应该有印象需要安装 zlib-devel、openssl-devel 和 libffi-devel 之类的系统依赖。但我们前面的问题比较简单,并不是有不同的编译依赖(系统级),而只是三方库依赖不同(项目级)。
  • 另一个主要的原因,Numpy 打包出的不同系统版本,并非简简单单地用 setuptools 之类的 Python 库就能打包,而是要借助标准的镜像进行构建。例如,manylinux 版本的打包,参见 Github(github.com/pypa/manyli…),就需要使用官方提供的 Docker 镜像。对于我们的问题,显然不想做到这么麻烦。

简而言之,根据前面的分析,如果要实现操作系统兼容的打包,维护多份依赖文件、使用不同构建包的方法、维护多系统专用的包,方法可行,但并不是很适用。

如果没有新的办法,这不失为一种考虑,但是有没有别的办法了呢?

我曾被这个问题困扰过,但是没有深入去研究解决,直到无意中在loguru 这个用来记录日志的库的 setup.py 中看到:

939f5411e14e2b5131b7bdb84c74bfd.png

再翻看大名鼎鼎的requests 库文件,发现还可以这样写:

7d789e8c9b1a24ecc0fe12c5ca5cbda.png

两个示例都是写在 setup.py 文件中,其实如果我们用 requirements.txt 文件,也可以按这种格式写,然后再读取进来。

这种神奇的写法是怎么回事呢?

它的依据是 2015 年 11 月创建的 PEP-508(以及相关的但已被撤销或拒绝了的 PEP-390、PEP-426、PEP-459、PEP-496),该 PEP 的主要意图是增强 pip 等工具查找软件包的能力。

98a974c489646fba2559b7e48e19505.png

比较重要的部分就是跟我们的问题相关的,即对操作系统作区分的标识,相关的有:

9db97c0126ce50a99c29b5110ced4b6.png

有了这样的扩展支持,在打包依赖项时,就可以解决兼容性问题了。

例如 colorama 库,如果我们只在 win32 系统才需要依赖,那么在打包时就可以指定:“colorama>=0.3.4 ; sys_platform=='win32' ”;如果不需要限定 win32 系统,而是在 windows 环境都安装,那么可以写成“colorama>=0.3.4 ; platform_system=='Windows' ”。


目录
相关文章
|
2月前
|
存储 索引 Python
Python小技巧:单下划线 '_' 原创
Python小技巧:单下划线 '_' 原创
|
3天前
|
Linux 开发者 iOS开发
深度剖析:Python如何优雅地跨越操作系统鸿沟,实现无缝对接
Python 作为一种高级编程语言,具有出色的跨平台特性,能够在 Windows、macOS 和 Linux 等多种操作系统上无缝运行。本文通过具体示例,介绍了 Python 如何利用其内置模块(如 `os` 和 `platform`)及第三方库(如 `pathlib` 和 Tkinter)实现代码的一致性和可移植性,帮助开发者轻松开发和部署应用。
14 3
|
4天前
|
Linux 开发者 iOS开发
Python系统调用实战:如何在不同操作系统间游刃有余🐟
本文介绍了 Python 在跨平台开发中的强大能力,通过实际例子展示了如何使用 `os` 和 `pathlib` 模块处理文件系统操作,`subprocess` 模块执行外部命令,以及 `tkinter` 创建跨平台的图形用户界面。这些工具和模块帮助开发者轻松应对不同操作系统间的差异,专注于业务逻辑。
17 2
|
25天前
|
Linux 区块链 Python
Python实用记录(十三):python脚本打包exe文件并运行
这篇文章介绍了如何使用PyInstaller将Python脚本打包成可执行文件(exe),并提供了详细的步骤和注意事项。
46 1
Python实用记录(十三):python脚本打包exe文件并运行
|
26天前
|
Python
Python实用记录(四):os模块-去后缀或者改后缀/指定目录下图片或者子目录图片写入txt/csv
本文介绍了如何使用Python的os模块来操作文件,包括更改文件后缀、分割文件路径和后缀、将指定目录下的所有图片写入txt文档,以及将指定目录下所有子目录中的图片写入csv文档,并为每个子目录分配一个标签。
15 1
|
1月前
|
Linux 开发者 iOS开发
深度剖析:Python如何优雅地跨越操作系统鸿沟,实现无缝对接
【10月更文挑战第2天】Python 作为一种高级编程语言,具备出色的跨平台特性,可在 Windows、macOS 和 Linux 上无缝运行。本文探讨 Python 如何通过核心特性和第三方库实现跨平台开发。内置模块如 `os` 和 `platform` 以及现代库 `pathlib`,简化了文件系统操作。对于 GUI 开发,Tkinter、PyQt 和 wxPython 等库提供了强大支持,确保应用程序的一致性和可移植性。通过具体示例,本文展示了如何利用这些工具应对不同操作系统的需求。
19 6
|
1月前
|
Linux 开发者 iOS开发
Python系统调用实战:如何在不同操作系统间游刃有余🐟
【10月更文挑战第2天】Python 以其卓越的跨平台能力和丰富的标准库,成为解决多操作系统环境下编程挑战的理想选择。本文将通过实际例子展示 Python 如何简化跨平台开发。从文件系统操作到系统调用,再到 GUI 应用开发,Python 提供了多种工具和模块,如 `os`、`pathlib` 和 `subprocess`,帮助开发者轻松应对不同平台间的差异,让你成为真正的跨平台高手。
16 5
|
30天前
|
Shell Python
Python 的 os 库的应用实例
Python 的 os 库的应用实例
|
1月前
|
Linux 开发者 iOS开发
跨界英雄Python:一招搞定跨平台兼容性难题🎯
【10月更文挑战第2天】Python 作为一种现代且灵活的编程语言,在处理跨平台兼容性方面表现出色。其标准库如 `os` 和 `pathlib` 以及第三方库使开发者能轻松编写高可移植性的代码。通过文件系统操作、执行外部命令及使用 Tkinter 创建 GUI 等示例,Python 展现了其强大的跨平台能力,让开发者专注于业务逻辑而非平台差异。掌握这些技巧,你将能在不同操作系统间游刃有余。
20 4
|
1月前
|
安全 测试技术 数据库
Python编程--sys模块及OS模块简单用例
Python编程--sys模块及OS模块简单用例