使用py2exe打包GTK资源

10
我正在使用来自全合一安装程序的Python 2.6和PyGTK 2.22.6在Windows XP上构建单个文件可执行文件(通过py2exe)。我的问题是,当我将应用程序作为脚本运行时(即未构建为.exe文件,只是一组松散的.py文件),它使用本地外观的Windows主题,但是当我运行已构建的exe时,我看到默认的GTK主题。我知道可以通过将一堆文件复制到由py2exe创建的dist目录中来解决此问题,但我阅读的所有内容都涉及手动复制数据,而我希望这成为构建过程的自动部分。此外,关于此主题的所有内容(包括FAQ)都已过时- PyGTK现在将其文件保存在C:\Python2x\Lib\site-packages\gtk-2.0\runtime\...中,仅复制libetc目录无法解决该问题。我的问题是:
  1. 我希望能够在setup.py中以编程方式查找GTK运行时数据,而不是硬编码路径。我该怎么做?

  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前缀,但是与相同的目录结构,在由py2exe生成的dist目录直接放置。但是,考虑到gtk.gtk_version(2,22,0),那么2.10.0从哪里来呢?

1个回答

8

在这里回答自己的问题,如果有更好的方法请随意回答。其中一些内容看起来相当脆弱(例如路径中的版本号),如果您知道更好的方法,请评论或编辑。

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. 需要包含哪些文件

这取决于(a)大小有多大的问题,和(b)应用程序部署的上下文。我指的是,您是将其部署到整个世界,任何人都可以拥有任意的本地设置,还是仅用于内部企业使用,您不需要翻译库存字符串?

如果你想要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"

如果你想要Tango图标:
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)
                        ])
                    ]
                )
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接