4

I am trying to "freeze" a Python 3 file that uses PyGObject and Gdk/Gtk. Here is the Python script:

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()

And here is my 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
)

This appears to build successfully. However, when I run the executable file, I get this error:

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.

Can anyone point me in the right direction to solving this problem? I'm not sure where I'm going wrong as I've tried to include all the missing DLLs but it still refuses to work. Alternatively, if anyone can point to a better method of packaging this as an executable, that would be appreciated too. I've tried py2exe but had no luck there either.

Thanks in advance.

Arc
  • 329
  • 3
  • 11
  • My tool [pynsist](http://pynsist.readthedocs.org/en/latest/) can make an installer from a pygtk application ([example files](https://github.com/takluyver/pynsist/tree/master/examples/pygtk)). I haven't tried it with the new `gi.repository` bindings, but it might be able to do that. – Thomas K Feb 21 '15 at 23:24
  • Having similar difficulties. Probably a bug. Will post bug report later: http://stackoverflow.com/questions/28794406/package-pygobject-python-3-program-with-pynsist – tobias47n9e Mar 07 '15 at 14:16
  • https://bugzilla.gnome.org/show_bug.cgi?id=745818 – tobias47n9e Mar 07 '15 at 17:55

2 Answers2

1
  1. To know the exact missing dlls You need to download and install: https://learn.microsoft.com/en-us/sysinternals/downloads/listdlls
  2. You have to copy missing dll files from c:\pythonXX\Lib\site-packages\gnome\XXX.dll to build\exe_your_executable
0

I had the same problem last year. It's really hard to guess which DLLs are required and which are not. I then started to include all DLLs, removed those I was unsure about one by one and checked if the program was still working. As far as I remember there wasn't many I could remove. If you're still interested in a working example, check out this one:
https://github.com/da-mkay/subsynco/blob/master/scripts/dist_win/setup.py
(However it uses also GStreamer and thus includes some more DLLs which might not be required by your project)

Biggie
  • 7,037
  • 10
  • 33
  • 42