PyGObject и cx_freeze в Windows

Я пытаюсь «заморозить» файл Python 3, который использует PyGObject и Gdk/Gtk. Вот скрипт Python:

from gi.repository import Gtk, Gdk

class Handler:
    def onDeleteWindow(self, *args):
        Gtk.main_quit(*args)

    def searchPressed(self, button):
        print("Hello World!")

builder = Gtk.Builder()
builder.add_from_file("glade/test.glade")
builder.connect_signals(Handler())
window = builder.get_object("window1")
style_provider = Gtk.CssProvider()
window.set_name("window1")
css = """
#window1 {
    background-color: #777777;
}
"""
style_provider.load_from_data(css.encode())
Gtk.StyleContext.add_provider_for_screen(
    Gdk.Screen.get_default(), 
    style_provider,     
    Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)
window.show_all()
Gtk.main()

А вот мой setup.py:

import os, site, sys
from cx_Freeze import setup, Executable

## Get the site-package folder, not everybody will install
## Python into C:\PythonXX
site_dir = site.getsitepackages()[1]
include_dll_path = os.path.join(site_dir, "gnome")

## Collect the list of missing dll when cx_freeze builds the app
missing_dll = ['libgtk-3-0.dll',
               'libgdk-3-0.dll',
               'libatk-1.0-0.dll',
               'libcairo-gobject-2.dll',
               'libgdk_pixbuf-2.0-0.dll',
               'libjpeg-8.dll',
               'libpango-1.0-0.dll',
               'libpangocairo-1.0-0.dll',
               'libpangoft2-1.0-0.dll',
               'libpangowin32-1.0-0.dll',
]

## We also need to add the glade folder, cx_freeze will walk
## into it and copy all the necessary files
glade_folder = 'glade'

## We need to add all the libraries too (for themes, etc..)
gtk_libs = ['etc',
            'lib',
            'share',
            'lib/gdk-pixbuf-2.0',
            'lib/girepository-1.0',
            'share/glib-2.0'
]

## Create the list of includes as cx_freeze likes
include_files = []
for dll in missing_dll:
    include_files.append((os.path.join(include_dll_path, dll), dll))

## Let's add glade folder and files
include_files.append((glade_folder, glade_folder))

## Let's add gtk libraries folders and files
for lib in gtk_libs:
    include_files.append((os.path.join(include_dll_path, lib), lib))

base = None

## Lets not open the console while running the app
if sys.platform == "win32":
    base = "Win32GUI"

executables = [
    Executable("gtktest.py",
               base=base
    )
]

buildOptions = dict(
    compressed = False,
    includes = ["gi"],
    packages = ["gi"],
    include_files = include_files
    )

setup(
    name = "gtktest",
    author = "Monty Python",
    version = "1.0",
    description = "GTK test",
    options = dict(build_exe = buildOptions),
    executables = executables
)

Кажется, это успешно построено. Однако, когда я запускаю исполняемый файл, я получаю эту ошибку:

Traceback (most recent call last):
  File "C:\Python34\lib\site-packages\cx_Freeze\initscripts\Console.py", line 27, in <module>
    exec(code, m.__dict__)
  File "gtktest.py", line 1, in <module>
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 2237, in _find_and_load
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 2212, in _find_and_load_unlocked
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 321, in _call_with_frames_removed
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 2237, in _find_and_load
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 2226, in _find_and_load_unlocked
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 1191, in _load_unlocked
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 1161, in _load_backward_compatible
  File "C:\Python34\lib\site-packages\gi\__init__.py", line 42, in <module>
    from . import _gi
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 2284, in _handle_fromlist
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 321, in _call_with_frames_removed
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 2237, in _find_and_load
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 2226, in _find_and_load_unlocked
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 1191, in _load_unlocked
  File "c:\python\32-bit\3.4\lib\importlib\_bootstrap.py", line 1161, in _load_backward_compatible
  File "ExtensionLoader_gi__gi.py", line 22, in <module>
  File "ExtensionLoader_gi__gi.py", line 14, in __bootstrap__
ImportError: DLL load failed: The specified module could not be found.

Может ли кто-нибудь указать мне правильное направление для решения этой проблемы? Я не уверен, где я ошибаюсь, поскольку я пытался включить все недостающие библиотеки DLL, но он все равно отказывается работать. В качестве альтернативы, если кто-нибудь может указать на лучший способ упаковки этого исполняемого файла, это тоже будет оценено. Я пробовал py2exe, но и там мне не повезло.

Заранее спасибо.


person Arc    schedule 20.02.2015    source источник
comment
Мой инструмент pynsist может создать установщик из приложения pygtk (файлы примеров). Я не пробовал это с новыми привязками gi.repository, но, возможно, он сможет это сделать.   -  person Thomas K    schedule 22.02.2015
comment
Имея аналогичные трудности. Вероятно, ошибка. Отчет об ошибке опубликуем позже: stackoverflow .com/questions/28794406/   -  person tobias47n9e    schedule 07.03.2015
comment
bugzilla.gnome.org/show_bug.cgi?id=745818   -  person tobias47n9e    schedule 07.03.2015


Ответы (2)


  1. Чтобы узнать точные отсутствующие библиотеки DLL, вам необходимо загрузить и установить: https://docs.microsoft.com/en-us/sysinternals/downloads/listdlls
  2. Вы должны скопировать отсутствующие файлы dll из c:\pythonXX\Lib\site-packages\gnome\XXX.dll в build\exe_your_executable
person El capitane    schedule 19.10.2018

У меня была такая же проблема в прошлом году. Очень сложно угадать, какие библиотеки DLL необходимы, а какие нет. Затем я начал включать все библиотеки DLL, удалял те, в которых не был уверен, одну за другой, и проверял, работает ли программа. Насколько я помню, их было не так много, чтобы я мог их удалить. Если вас все еще интересует работающий пример, посмотрите этот:
https://github.com/da-mkay/subsynco/blob/master/scripts/dist_win/setup.py
(однако он также использует GStreamer и, следовательно, включает в себя еще несколько DLL которые могут не требоваться вашим проектом)

person Biggie    schedule 29.02.2016