Объединение ресурсов GTK с py2exe - PullRequest
11 голосов
/ 25 октября 2011

Я использую Python 2.6 и PyGTK 2.22.6 из установщика all-in-one в Windows XP, пытаюсь создать исполняемый файл из одного файла (через py2exe )для моего приложения.

Моя проблема в том, что когда я запускаю свое приложение как скрипт (т.е. не встроенный в файл .exe, просто как свободную коллекцию файлов .py), он использует нативный-просматривая тему Windows, но когда я запускаю встроенный exe-файл, я вижу стандартную тему GTK.

Я знаю, что эту проблему можно исправить, скопировав кучу файлов в каталог dist, созданный py2exe, новсе, что я прочитал, включает в себя ручное копирование данных, в то время как я хочу, чтобы это было автоматической частью процесса сборки.Более того, все по теме (включая FAQ ) устарело - PyGTK теперь сохраняет свои файлы в C:\Python2x\Lib\site-packages\gtk-2.0\runtime\..., и простое копирование каталогов lib и etc не решает проблему.

Мои вопросы:

  1. Я бы хотел иметь возможность программно находить данные времени выполнения GTK в setup.py, а не в путях жесткого кодирования.Как мне это сделать?

  2. Какие минимальные ресурсы мне нужно включить?

Обновление: Могупочти ответили # 2 методом проб и ошибок.Чтобы тема «wimp» (т.е. MS Windows) работала, мне нужны файлы из:

runtime\lib\gtk-2.0\2.10.0\engines\libwimp.dll
runtime\etc\gtk-2.0\gtkrc
runtime\share\icons\*
runtime\share\themes\MS-Windows

... без префикса runtime, но в остальном с той же структурой каталогов, расположенной непосредственнов каталоге dist, созданном py2exe.Но откуда берется 2.10.0, учитывая, что gtk.gtk_version равно (2,22,0)?

1 Ответ

9 голосов
/ 27 октября 2011

Отвечая на мой вопрос здесь, но, если кто-нибудь знает, лучше не стесняйтесь отвечать тоже. Некоторые из них кажутся довольно хрупкими (например, номера версий в путях), поэтому комментируйте или редактируйте, если вы знаете лучший способ.

1. Поиск файлов

Во-первых, я использую этот код, чтобы фактически найти корень среды выполнения GTK. Это очень специфично для того, как вы устанавливаете среду выполнения, и, вероятно, может быть улучшено с помощью ряда проверок для общих расположений:

#gtk file inclusion
import gtk
# The runtime dir is in the same directory as the module:
GTK_RUNTIME_DIR = os.path.join(
    os.path.split(os.path.dirname(gtk.__file__))[0], "runtime")

assert os.path.exists(GTK_RUNTIME_DIR), "Cannot find GTK runtime data"

2. Какие файлы включить

Это зависит от (а) степени озабоченности и (б) контекста развертывания вашего приложения. Под этим я подразумеваю, вы развертываете его во всем мире, где любой может иметь произвольную настройку локали, или это только для внутреннего корпоративного использования, где вам не нужны переведенные строки акций?

Если вы хотите использовать темы Windows, вам нужно будет указать:

GTK_THEME_DEFAULT = os.path.join("share", "themes", "Default")
GTK_THEME_WINDOWS = os.path.join("share", "themes", "MS-Windows")
GTK_GTKRC_DIR = os.path.join("etc", "gtk-2.0")
GTK_GTKRC = "gtkrc"
GTK_WIMP_DIR = os.path.join("lib", "gtk-2.0", "2.10.0", "engines")
GTK_WIMP_DLL = "libwimp.dll"

Если вам нужны значки танго:

GTK_ICONS = os.path.join("share", "icons")

Есть также данные локализации (которые я опускаю, но вы, возможно, не захотите):

GTK_LOCALE_DATA = os.path.join("share", "locale")

3. Кусок вместе

Во-первых, вот функция, которая обходит дерево файловой системы в заданной точке и выдает выходные данные, подходящие для опции data_files.

def generate_data_files(prefix, tree, file_filter=None):
    """
    Walk the filesystem starting at "prefix" + "tree", producing a list of files
    suitable for the data_files option to setup(). The prefix will be omitted
    from the path given to setup(). For example, if you have

        C:\Python26\Lib\site-packages\gtk-2.0\runtime\etc\...

    ...and you want your "dist\" dir to contain "etc\..." as a subdirectory,
    invoke the function as

        generate_data_files(
            r"C:\Python26\Lib\site-packages\gtk-2.0\runtime",
            r"etc")

    If, instead, you want it to contain "runtime\etc\..." use:

        generate_data_files(
            r"C:\Python26\Lib\site-packages\gtk-2.0",
            r"runtime\etc")

    Empty directories are omitted.

    file_filter(root, fl) is an optional function called with a containing
    directory and filename of each file. If it returns False, the file is
    omitted from the results.
    """
    data_files = []
    for root, dirs, files in os.walk(os.path.join(prefix, tree)):        
        to_dir = os.path.relpath(root, prefix)

        if file_filter is not None:
            file_iter = (fl for fl in files if file_filter(root, fl))
        else:
            file_iter = files

        data_files.append((to_dir, [os.path.join(root, fl) for fl in file_iter]))

    non_empties = [(to, fro) for (to, fro) in data_files if fro]

    return non_empties

Так что теперь вы можете звонить setup() вот так:

setup(
    # Other setup args here...

    data_files = (
                    # Use the function above...
                    generate_data_files(GTK_RUNTIME_DIR, GTK_THEME_DEFAULT) +
                    generate_data_files(GTK_RUNTIME_DIR, GTK_THEME_WINDOWS) +
                    generate_data_files(GTK_RUNTIME_DIR, GTK_ICONS) +

                    # ...or include single files manually
                    [
                        (GTK_GTKRC_DIR, [
                            os.path.join(GTK_RUNTIME_DIR,
                                GTK_GTKRC_DIR,
                                GTK_GTKRC)
                        ]),

                        (GTK_WIMP_DIR, [
                            os.path.join(
                                GTK_RUNTIME_DIR,
                                GTK_WIMP_DIR,
                                GTK_WIMP_DLL)
                        ])
                    ]
                )
)
...