我想用pynsist打包一个Python3-PyGObject程序。该存储库有一个PyGTK的示例,它使我认为更改示例应该不难。

该示例可以在这里找到:


https://github.com/takluyver/pynsist/tree/master/examples/pygtk


在这个文件(https://github.com/takluyver/pynsist/blob/master/examples/pygtk/grab_files.sh)中,我认为只需抓取针对GTK 3(http://www.gtk.org/download/win32.php)的文件:

wget -O gtkbundle.zip http://win32builder.gnome.org/gtk+-bundle_3.6.4-20130921_win32.zip
wget -O pygobject.exe http://sourceforge.net/projects/pygobjectwin32/files/pygi-aio-3.14.0_rev12-setup.exe/download
wget -O pycairo.zip http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/cairo_1.10.2-2_win32.zip


我不确定第四行该怎么做,因为我目前的理解是这些绑定应该已经在gtk或pygobject包中:

 wget -O pygtk.exe http://ftp.gnome.org/pub/GNOME/binaries/win32/pygtk/2.24/pygtk-2.24.0.win32-py2.7.exe


然后,我尝试自定义此文件(https://github.com/takluyver/pynsist/blob/master/examples/pygtk/installer.cfg)以包括(使用gi而不是gi.repository):

[Include]
packages=gi


产生的错误是:

raise ExtensionModuleMismatch(extensionmod_errmsg % ('Windows', path))nsist.copymodules.ExtensionModuleMismatch: Found an extension module that will not be usable on Windows:/usr/lib/python3/dist-packages/gi/_gi.cpython-34m-x86_64-linux-gnu.soPut Windows packages in pynsist_pkgs/ to avoid this.

有谁知道程序的正确方法(例如其中之一:https://python-gtk-3-tutorial.readthedocs.org)是什么?

编辑1

在Windows上打包并安装程序之后,启动测试程序将产生以下回溯:

Traceback (most recent call last):
  File "C:\Program Files (x86)\hellogtk\hellogtk.launch.pyw", line 31, in <module>
    from gtk_test import main
  File "C:\Program Files (x86)\hellogtk\pkgs\gtk_test.py", line 3, in <module>
    from gi.repository import Gtk
  File "C:\Program Files (x86)\hellogtk\pkgs\gi\__init__.py", line 42, in <module>
    from . import _gi
ImportError: DLL load failed: The specified module could not be found.


发生此ImportError异常是因为与_gi.pyd在同一目录(gi)中有一个__init__.py文件

这是当前布局:

 - directory
 |- pynsist_pkgs
 |-- cairo
 |--- _cairo.pyd
 |--- __init__.py
 |-- gi
 |--- _gobject
 |--- overrides
 |--- repository
 |--- __init__.py
 |--- _gi.pyd
 |--- ...
 |-- gtk
 |--- bin
 |--- etc
 |--- lib
 |--- manifest
 |--- share
 |-- dbus
 |--- __init__.py
 |--- ...
 |-- gnome
 |--- ...
 |-- pygtkcompat
 |--- ...
 |-- _dbus_bindings.pyd
 |-- _dbus_glib_bindings.pyd
 |-- ...
 |- gtk_test.py
 |- grab_files.sh
 |- installer.cfg
 |- gtk_preamble.py


我使用了pygobject绑定的py-3.4-64文件夹。我在其上创建程序包的Linux是64位,而我正在运行该程序的Windows也是64位。

编辑2:

使用Dependency-Walker,我可以看到缺少2个DLL:GPSVC.DLLIESHIMS.DLL

编辑3:

我在系统上找到了这2个DLL,并将它们复制到测试程序的不同目录中,但是没有用。

编辑4:

这对于导入错误可能很有用:


import gtk/glib produces ImportError: DLL load failed

最佳答案

我与pynsist的作者Thomas K一起解决了这个问题。我确实想宣传一下,它是一个很好的工具,具有很好的支持,在我看来,它使打包数量级变得更加容易。

我的方法有很多错误(请参阅问题),因此描述正确的方法可能会更容易:

下载依赖项

仅导入程序的唯一依赖项:

 from gi.repository import Gtk


是可以在此处下载的最新pygi-aio(当前为pygi-aio-3.14)捆绑包(pynsist-repository中的示例具有下载脚本,但是我可能需要更新以获取较新的版本):


https://sourceforge.net/projects/pygobjectwin32/files/


提取依赖项

现在已经合并到pynsist-repository中的PyGObject / PyGI示例带有一个脚本,该脚本从捆绑包中提取必要的依赖项(请参见:https://github.com/takluyver/pynsist/tree/master/examples/pygi_mpl_numpy)。

最重要的是,它提取绑定zip文件的内容(修改目标Python版本和位的脚本)并将它们复制到pynsist_pkgs文件夹中:

  - cairo
  - dbus
  - gi
  - gnome
  - pygtkcompat


然后,提取子依赖项并将其复制到pynsist_pkgs/gnome/文件夹中。正如lazka所指出的,一个典型的最小Gtk程序的最低要求是(每个库都有一个pygi/noarchpygi/[TargetedArchitecture] zip文件):

 - ATK
 - Base
 - Gdk
 - GDKPixbuf
 - GTK
 - JPEG
 - Pango
 - WebP
 - TIFF


生成安装程序

在我的情况下,安装程序是使用以下命令构建的:

 python3 -m nsist installer.cfg


installer.cfg也在存储库示例文件夹中。它只需要列出gnome(gnome文件夹中的子依赖项作为一个单元)。

关于pygi-aio软件包的注意事项

在Windows机器上安装pygi-aio时,安装程​​序将执行一些安装后编译步骤。如果使用这种方法,这可能会成为问题,因为它仅提取依赖项。在某些情况下,您可能需要运行exe文件(捆绑包随附)并将已编译的文件复制回构建目录中。我描述我在这里遇到的唯一问题:


https://github.com/tobias47n9e/innsbruck-stereographic/issues/1


这里有一个错误报告,其中包含更多信息:


https://sourceforge.net/p/pygobjectwin32/tickets/12/


工作实例

您可以在此处获得示例:


https://github.com/takluyver/pynsist/tree/master/examples/pygi_mpl_numpy

10-06 14:31