为Windows创建一个包。

备注

本文档仅适用于Kivy 1.9.1 及以上版本。

在Windows平台上打包应用程序只能在Windows操作系统内进行。以下流程已在Windows上使用Kivy **wheels**安装进行了测试,其他安装方式请参见文末。

该软件包将是32位或64位,具体取决于您运行它时使用的Python版本。

要求

  • 最新版Kivy(按照:ref:`installation_windows`中描述的方式安装)。

  • PyInstaller 3.1+(pip install --upgrade pyinstaller)。

PyInstaller 默认钩子

本节内容适用于包含kivy钩子的PyInstaller(>=3.1)。若要覆盖默认钩子,以下示例需稍作修改。参见:ref:overwrite-win-hook

打包一个简单的应用

在本示例中,我们将打包**touchtracer**示例项目,并嵌入自定义图标。当使用wheel包安装时,Kivy示例位于``python\share\kivy-examples``;若从GitHub源码安装,则位于``kivy\examples``。我们将指向示例的完整路径简称为``examples-path``。touchtracer示例位于``examples-path\demo\touchtracer``,主文件名为``main.py``。

  1. 打开你的命令行终端,并确保Python已在系统路径中(即输入``python``命令可以正常工作)。

  2. 创建一个文件夹,用于存放打包后的应用程序。例如,创建一个``TouchApp``文件夹,并使用例如``cd TouchApp``命令`切换到该目录 <https://www.computerhope.com/cdhlp.htm>`_。然后输入:

    python -m PyInstaller --name touchtracer examples-path\demo\touchtracer\main.py
    

    你也可以在应用程序文件夹中添加一个 icon.ico 文件,以便为可执行文件创建图标。如果你没有可用的 .ico 文件,可以使用网页应用 ConvertICO 将你的 icon.png 文件转换为 ico 格式。将 icon.ico 保存在 touchtracer 目录中,然后输入:

    python -m PyInstaller --name touchtracer --icon examples-path\demo\touchtracer\icon.ico examples-path\demo\touchtracer\main.py
    

    更多选项,请参阅 PyInstaller 手册

  3. 规格文件将是位于``TouchApp``中的``touchtracer.spec``。现在我们需要编辑规格文件,添加依赖钩子以正确构建exe。用你喜欢的编辑器打开规格文件,并在规格文件的开头添加以下行(假设使用sdl3,现在默认如此):

    from kivy_deps import sdl3, glew
    

    然后,找到``COLLECT()``并为touchtracer(touchtracer.kvparticle.png`等)添加数据:修改该行以添加一个``Tree()``对象,例如``Tree('examples-path\demo\touchtracer\')`。这个Tree将搜索并添加touchtracer目录中找到的每个文件到你的最终包中。

    要添加依赖项,请在COLLECT中的第一个关键字参数之前,为每个依赖路径添加一个Tree对象。例如:*[Tree(p) for p in (sdl3.dep_bins + glew.dep_bins)],这样看起来会像这样:

    coll = COLLECT(exe, Tree('examples-path\\demo\\touchtracer\\'),
                   a.binaries,
                   a.zipfiles,
                   a.datas,
                   *[Tree(p) for p in (sdl3.dep_bins + glew.dep_bins)],
                   strip=False,
                   upx=True,
                   name='touchtracer')
    
  4. 现在我们在 TouchApp 中构建规格文件,如下所示:

    python -m PyInstaller touchtracer.spec
    
  5. 编译后的包将位于 TouchApp\dist\touchtracer 目录中。

单文件应用程序

接下来,我们将修改上述示例,将 touchtracer 示例项目打包为单文件应用程序。按照上述相同步骤,改为执行以下命令:

python -m PyInstaller --onefile --name touchtracer examples-path\demo\touchtracer\main.py
  1. 和之前一样,这将生成touchtracer.spec文件,我们将编辑该文件以添加依赖项。在此实例中,编辑EXE命令的参数,使其看起来类似如下:

    exe = EXE(pyz, Tree('examples-path\\demo\\touchtracer\\'),
         a.scripts,
         a.binaries,
         a.zipfiles,
         a.datas,
         *[Tree(p) for p in (sdl3.dep_bins + glew.dep_bins)],
         upx=True,
         name='touchtracer')
    
  2. 现在你可以像之前一样构建spec文件,使用:

    python -m PyInstaller touchtracer.spec
    
  3. 编译后的包将位于`TouchApp\dist`目录中,由单个可执行文件组成。

打包数据文件

我们将再次修改之前的示例,以包含打包的数据文件。PyInstaller允许包含项目运行所需的外部数据文件(如图像、数据库等)。在Windows上运行应用时,可执行文件会解压到一个临时文件夹,而Kivy项目并不知道这个位置,因此无法定位这些数据文件。我们可以通过几行代码来解决这个问题。

  1. 首先,请遵循PyInstaller文档中关于如何在应用程序中包含数据文件的说明。

  2. 修改你的主 Python 代码,使其包含以下导入(如果尚未包含的话):

    import os, sys
    from kivy.resources import resource_add_path, resource_find
    
  3. 修改你的主 Python 代码,使其包含以下内容(以 touchtracer 应用为例):

    if __name__ == '__main__':
        if hasattr(sys, '_MEIPASS'):
            resource_add_path(os.path.join(sys._MEIPASS))
        TouchtracerApp().run()
    
  4. 最后,按照上述步骤打包你的应用程序。

使用 GStreamer 打包视频应用

接下来,我们将稍微修改上面的示例,以打包一个使用gstreamer进行视频播放的应用。我们将使用位于``examples-pathwidgetsvideoplayer.py``的``videoplayer``示例。在某个位置创建一个名为``VideoPlayer``的文件夹,并在命令行中将当前目录切换到该文件夹,然后执行:

python -m PyInstaller --name gstvideo examples-path\widgets\videoplayer.py

要创建``gstvideo.spec``文件。按上述方式编辑,这次同时包含gstreamer依赖项:

from kivy_deps import sdl3, glew, gstreamer

并添加 Tree() 以包含视频文件,例如 Tree('examples-path\\widgets'),以及 gstreamer 依赖项,因此它应该看起来像这样:

coll = COLLECT(exe, Tree('examples-path\\widgets'),
               a.binaries,
               a.zipfiles,
               a.datas,
               *[Tree(p) for p in (sdl3.dep_bins + glew.dep_bins + gstreamer.dep_bins)],
               strip=False,
               upx=True,
               name='gstvideo')

然后在 VideoPlayer 中构建 spec 文件,使用:

python -m PyInstaller gstvideo.spec

你应该能在 VideoPlayer\dist\gstvideo 中找到 gstvideo.exe,运行它即可播放视频。

覆盖默认钩子

包含/排除视频和音频以及减小应用体积

PyInstaller 包含一个针对 Kivy 的钩子,默认会添加 Kivy 使用的**所有**核心模块,例如音频、视频、拼写等(你仍然需要使用 Tree() 手动打包 gstreamer DLL——参见上面的示例)及其依赖项。如果该钩子未安装,或为了减小应用体积,可以通过替代钩子排除其中一些模块,例如,如果不使用音频/视频。

Kivy 在 hookspath() 处提供了备用钩子。此外,当且仅当 PyInstaller 没有默认钩子时,还必须提供 runtime_hooks()。在覆盖钩子时,通常不需要覆盖后者。

备选的 hookspath() 钩子不包含任何 Kivy 提供者。要添加它们,必须通过 get_deps_minimal()get_deps_all() 来添加。更多详情请参阅它们的文档和 pyinstaller_hooks。但本质上,get_deps_all() 会像默认钩子一样添加所有提供者,而 get_deps_minimal() 仅添加应用运行时加载的那些提供者。每种方法都会提供一个隐藏的 Kivy 导入和排除导入的列表,这些可以传递给 Analysis

也可以生成一个备用的钩子,它逐一列出所有Kivy提供者模块,不需要的模块可以注释掉。参见 pyinstaller_hooks

要使用上述示例中的备用钩子,请按以下方式修改,通过``hookspath()``和``runtime_hooks``(如需要)添加钩子,并使用``**get_deps_minimal()``或``**get_deps_all()``来指定提供者。

例如,添加导入语句:

from kivy.tools.packaging.pyinstaller_hooks import get_deps_minimal, get_deps_all, hookspath, runtime_hooks

然后按如下方式修改 Analysis:

a = Analysis(['examples-path\\demo\\touchtracer\\main.py'],
             ...
             hookspath=hookspath(),
             runtime_hooks=runtime_hooks(),
             ...
             **get_deps_all())

要包含所有内容,就像默认钩子一样。或者:

a = Analysis(['examples-path\\demo\\touchtracer\\main.py'],
             ...
             hookspath=hookspath(),
             runtime_hooks=runtime_hooks(),
             ...
             **get_deps_minimal(video=None, audio=None))

例如,要排除音频和视频提供者,而对于其他核心模块,仅使用已加载的那些。

关键点在于提供备选的 hookspath(),它默认不列出所有 Kivy 提供者,而是通过 get_deps_minimal() 手动将所需的提供者添加到 hiddenimports,同时移除不需要的提供者(在此示例中为音频和视频)。

其他安装方式

之前的示例使用了如 *[Tree(p) for p in (sdl3.dep_bins + glew.dep_bins + gstreamer.dep_bins)], 这样的代码,以便让 PyInstaller 添加这些依赖项所使用的所有 DLL 文件。如果 Kivy 不是通过 wheels 方法安装的,这些命令将无法正常工作,例如 kivy_deps.sdl3 将无法导入。在这种情况下,必须找到这些 DLL 文件的位置,并以与示例类似的方式手动将它们传递给 Tree 类。