使用 MingW 在 Windows 上传送 PyGObject/GTK+ 应用程序

kak*_*kyo 2 python windows gtk deployment

我在 Windows 上使用 PyGObject/GTK+ 和 Python3.7,并且担心如何打包我的应用程序。借助Python官方生态系统,可以轻松使用冷冻机和venvs。然而,Windows 上的 PyGObject 和 GTK+ 需要 MingW 环境才能运行。

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

kak*_*kyo 6

由于没有人很快关心,我将在这里报告我的发现。截至我撰写本文之日,简短的回答是:PyGObject 生态系统尚未在 Windows 上实现商业化,尽管没有什么可以阻止您发布功能性应用程序。

问题在于 Windows 上缺少 PyGOBject 的功能冻结器。所以你不能真正用它来发布一个闭源商业产品(尽管有人可能会说整个 Python 生态系统并不是为此而设计的)。我尝试过的冰箱:

  1. PyInstaller目前官方推荐的不随官方推荐的msys/MingGWuniverse安装;即使从源代码构建 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
Run Code Online (Sandbox Code Playgroud)
  1. cx_Freeze另一个著名的替代方案,也不在 MingW 上构建/安装。无论您安装多少个 gcc 变体,您最终都会遇到 gcc 问题。
  2. py2exe自 Python 3.4 起现在已被废弃。

由于 PyGObject 应用程序仍然使用 MinGW python 运行,因此为 Windows 提供这样的应用程序并非不可能。但这意味着你将带着大件行李出发,并想办法自己收拾所有东西。更不用说维持整个混乱了。请注意,如果您的应用程序是跨平台的,则 Mac 上的过程会有所不同。根据我的测试,PyInstaller 可在 Mac 上运行。

QuodLibet提供了如何发布基于 PyGObject 的开源软件的示例。不幸的是,截至今天,上游的打包过程build.sh在我的 Windows 10 上运行失败:

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

Run Code Online (Sandbox Code Playgroud)

事实证明,这是一个简单的解决方案:非 UTF8 Windows 上的区域设置问题。一个简单的补丁就是将“utf-8”替换为locale.getdefaultlocale(). 之后,构建成功。

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

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