【问题标题】:Bundling GTK resources with py2exe使用 py2exe 捆绑 GTK 资源
【发布时间】:2021-05-08 16:00:09
【问题描述】:

我在 Windows XP 上使用来自 all-in-one installer 的 Python 2.6 和 PyGTK 2.22.6,试图为我的应用构建一个单文件可执行文件(通过 py2exe)。

我的问题是,当我将我的应用程序作为脚本运行时(即,没有内置到 .exe 文件中,只是作为 .py 文件的松散集合),它使用看起来很原生的 Windows 主题,但是当我运行构建的 exe,我看到了默认的 GTK 主题。

我知道这个问题可以通过将一堆文件复制到由 py2exe 创建的dist 目录中来解决,但是我所阅读的所有内容都涉及手动复制数据,而我希望这是自动的一部分构建过程。此外,关于该主题的所有内容(包括 the 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目录中。但是2.10.0 是从哪里来的,因为gtk.gtk_version(2,22,0)

【问题讨论】:

    标签: python pygtk py2exe


    【解决方案1】:

    在这里回答我自己的问题,但如果有人知道更好,请随时回答。其中一些看起来很脆弱(例如路径中的版本号),因此如果您知道更好的方法,请发表评论或编辑。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-15
      • 1970-01-01
      • 2015-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-30
      相关资源
      最近更新 更多