使用 MingW 在 Windows 上运送 PyGObject/GTK+ 个应用

Shipping PyGObject/GTK+ app on Windows with MingW

我在 Windows 上使用 PyGObject/GTK+ 和 Python3.7,并且担心如何打包我的应用程序。有了官方的 Python 生态系统,freezers 和 venvs 就可以轻松使用了。但是,Windows 上的 PyGObject 和 GTK+ 需要 MingW 环境 运行。

这是否意味着我必须将整个 MingW 与 GTK+ 一起打包? 我应该如何冻结应用程序?

因为很快就没人关心了,我将在这里报告我的发现。简短的回答,截至我写这篇 post 的日期,是:PyGObject 生态系统在 Windows 上还没有商业准备,尽管没有什么能阻止你来自发布功能性应用程序。

交易破坏者是 Windows 上缺少 PyGOBject 的功能冻结器。所以你不能真正用它来发布一个封闭源代码的商业产品(尽管有人可能会争辩说整个 Python 生态系统不是为此而设计的)。我试过的冰箱:

  1. 官方推荐的PyInstaller right now does not install with the officially recommended msys/MingGW宇宙;即使在从源代码构建 PyInstaller 之后,冻结的 .exe 也会崩溃并抱怨缺少模块。以下是来自 hello-world 应用程序的崩溃报告。
$ app.exe
[8340] mod is NULL - structTraceback (most recent call last):
  File "C:/Apps/msys64/mingw64/lib/python3.7/struct.py", line 13, in <module>
    from _struct import *
ModuleNotFoundError: No module named '_struct'
[8340] mod is NULL - pyimod02_archiveTraceback (most recent call last):
  File "C:/Apps/msys64/mingw64/lib/python3.7/site-packages/pyinstaller-3.5-py3.7.egg/PyInstaller/loader/pyimod02_archive.py", line 28, in <module>
    import struct
ModuleNotFoundError: No module named 'struct'
[8340] mod is NULL - pyimod03_importersTraceback (most recent call last):
  File "C:/Apps/msys64/mingw64/lib/python3.7/site-packages/pyinstaller-3.5-py3.7.egg/PyInstaller/loader/pyimod03_importers.py", line 24, in <module>
    from pyimod02_archive import ArchiveReadError, ZlibArchiveReader
ModuleNotFoundError: No module named 'pyimod02_archive'
Traceback (most recent call last):
  File "site-packages/pyinstaller-3.5-py3.7.egg/PyInstaller/loader/pyiboot01_bootstrap.py", line 15, in <module>
ModuleNotFoundError: No module named 'pyimod03_importers'
[8340] Failed to execute script pyiboot01_bootstrap
  1. cx_Freeze,另一个突出的选择,在 MingW 上也没有 build/install。无论您安装了多少 gcc 变体,您最终都会遇到 gcc 问题。
  2. py2exe 现在是自 Python 3.4.
  3. 以来的废弃软件

由于 PyGObject 应用程序仍然 运行 与 MinGW python 一起使用,因此为 Windows 发布这样的应用程序并非不可能。但这意味着您将背着大包袱,想办法自己打包所有东西。更不用说维持整个烂摊子了。请注意,如果您的应用是跨平台的,Mac 上的过程会有所不同。根据我的测试,PyInstaller 在 Mac 上工作。

QuodLibet provides an example of how to ship an open-source software based on PyGObject. Unfortunately, as of today, the upstream's packaging procedure 在我的 Windows 10 上的 build.sh 运行 处失败:

copying data/quodlibet.zsh -> E:\_dev\quodlibet\win_installer\_build_root\mingw64\share\zsh\vendor-completions\_quodlibet
Traceback (most recent call last):
  File "E:/_dev/quodlibet/win_installer/misc/depcheck.py", line 141, in <module>
    main(sys.argv)
  File "E:/_dev/quodlibet/win_installer/misc/depcheck.py", line 130, in main
    libs = get_things_to_delete(sys.prefix)
  File "E:/_dev/quodlibet/win_installer/misc/depcheck.py", line 108, in get_things_to_delete
    for lib in get_dependencies(path):
  File "E:/_dev/quodlibet/win_installer/misc/depcheck.py", line 66, in get_dependencies
    data = data.decode("utf-8")
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa3 in position 72: invalid start byte

事实证明这很容易解决:非 UTF8 上的区域设置问题 Windows。 一个简单的补丁是用 locale.getdefaultlocale() 替换 "utf-8"。之后,构建成功。

然而,全球分销问题仍然具有挑战性:

  • 膨胀的管道:官方推荐的 msys2 构建系统基本上将整个 GNOME 宇宙和大部分 Python 宇宙拖到您的机器上,而您可能已经有了一个 Python 环境在你的母语 Windows 上。事实证明,很难从这一堆东西中挑选出必要的依赖项。
  • 构建可执行文件需要额外的 C 管道。要在没有冷冻器的情况下构建 Windows 可执行文件,您必须将您的应用程序创建为 Python 包(大麻烦),将其安装到您的 msys2-Python 站点包(另一个 setup.py 麻烦),然后使用 Python C API(不透明的麻烦)构建包装器 C 应用程序。该过程不透明,尤其是当 Python 打包系统对工作目录和路径差异敏感时。如果没有太多调试信息,启动可执行文件很容易出错。
  • 手动剥离。如上所述,您必须手动挑选依赖项,否则您的应用程序将基本上包含整个 msys2/MinGW 宇宙,对于一个 hello-world 应用程序来说价值 100MB+。