我想用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.DLL
和IESHIMS.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/noarch
和pygi/[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