1 发布到 pypi

setup.py 这套东西已经很成熟了, 不再赘述, 当前主流的是 twine + wheel 的方式, 好处很简单, 就是 pip install 安装方式省心省力目前也比较流行 poetry 这个库的 publish 功能进行发布

2 作为 pyz 发布

Shiv

有 PEP441 的加成, 目前 Shiv 在这方面做的已经非常熟练了:

  1. 通过 pip 收集所需要的第三方库
  2. 通过 shebang 来指定 Python 解释器路径
  3. 通过 zipapp 相关功能把整个 package 打包成一个 pyz 压缩文件(实质是zip文件换了个扩展名)
  4. 通过 _bootstrap 指定执行条件 module:app
  5. 通过命令行执行整个打包过程

优点:

  1. 单文件上传下载简单方便
  2. 可以直接使用 python xxx.pyz 来执行 package 里的 main.py
  3. 也可以将 xxx.pyz 当作一个环境, 来执行其它的 py 脚本, 比如 python xxx.pyz a.py
  4. 省去了重新 pip 下载编译的过程, 而且也避免了缺少编译环境而无法安装 C 扩展, 即在打包机编译, 在生产环境直接执行
  5. 对于纯 Python 的依赖, 可以跨多个平台使用, 配合 shebang 更省去了查找解释器路径的过程
  6. 如果在 Windows 系统, 可以使用官方的嵌入式(embed)Python作为绿色版解释器一起打包, 省去了安装环境的过程
  7. pyz 文件在内存里解压, 不会额外占用临时文件夹的空间 (不确定)

缺点:

  1. 在不同操作系统打包的时候, 如果遇到需要编译的基于 C 语言的库, 编译出的环境不能通用
  2. 依然离不开解释器
  3. 对于 __file__ 这种内置变量, 可能会导致定位内部某个文件路径时出问题

傻瓜式 pyz 打包从开始到放弃

曾想过写一个 GUI 来搞定打包 pyz 应用的整个过程

  1. 选择 module 路径
  2. 选择执行方式
  3. 安装 pip requirements
  4. 对 Python3.7+ 版本开启压缩选项
  5. 自动包装 __main__.py
  6. 对 Windows 系统支持去官网下载 embed 的解释器
  7. 选择 Python shebang, 可以支持上述 embed 解释器的相对路径一起打包

花 2 天折腾了几部分感觉吃力不讨好, 而且也不是什么急切的需要, 就搁置到一边了, 就算有急切需要, 平时 shiv 打包的已经足够好用, 所以 GUI 不是太着急用到

3 Windows 可执行程序

早年间 pyinstaller 因为不太成熟, 所以用的是 cx_freeze, 此外还有 py2app py2exe 之类的打包工具, 当时也有各种缺少头文件或环境依赖文件的 issue 要自己手动修复, 尤其是 pyqt 这种需要大量编译的情况2019 年来说, pyinstaller 已经非常成熟了, 而且文档也比较短, 所以基本只使用这个工具, 就可以满足绝大多数日常需要了

pyinstaller 的优点

  1. 文档简洁, 功能不复杂, 主要操作的参数也都一看就懂
  2. 不需要指定依赖的第三方库列表, 只要环境可以成功运行, 就会自动打包起来
  3. 支持多个平台打包 exe
  4. 打包速度比较快, 可以一起打包一些二进制文件或者其它类型的素材
  5. 支持单文件, 压缩, icon 等常用功能

pyinstaller 的缺点

  1. 单文件打包的时候, 要注意执行的时候如果不是正常退出(比如直接杀死进程, 或者抛错), 会导致临时目录里的冗余文件在执行以后无法自动清理掉, 因为它的实现原理就是解压缩到临时文件夹下来执行的; 不过一般如果使用的是 GUI 程序, 这种问题遇到的较少, 因为大多数 GUI 程序的关闭不是直接杀死进程, 而是关闭窗口
  2. 有些隐藏的问题会导致打包卡住, 比如 icon 不合法
  3. 如果在全局环境直接打包, 会打包一大堆多余的库进来. 解决方法是在虚拟环境里面打包, 对此, 之前我实现了一个Pyinstaller terminal UI 可以比较傻瓜式地按步骤打包, 创建的临时虚拟环境也可以打包完随手删掉

通过 PyinstallerUI 简化打包流程

pip install pyinstallerui -U

具体文档参考 https://github.com/ClericPy/pyinstallerui其实主要解决的问题是:

  1. 傻瓜式 UI 操作避免背命令行参数
  2. 在终端拖拽方式省去复制粘贴文件路径
  3. checkbox 方式通过多选开关一些功能参数
  4. 创建和删除临时虚拟环境, 避免打包时全局环境的库一起被打包, 浪费空间
    1. 一般专用虚拟环境下打包一些纯 Python 依赖的应用, 占用空间 9MB 左右
  5. 自动安装缺失的 pip 环境
  6. 打包前可以先执行测试, 避免打包完发现无法使用
  7. 打包完毕后自动清理垃圾文件

小结

现实中生产环境下的 deploy 却很少用到, 虽然 shiv 是 linkedin 以前挺喜欢的打包发布方式吧. 现在生产环境的发布, 大都走了主流的 CI/CD 套件, 有 docker 或者 gitflow 加成, 更稳定高效.所以, 以上就是闲聊的方式回顾一下之前用到的打包方式, 也是平时玩乐脚本分享给他人会用一下