Kivy Windows 应用打包实战:基于 PyInstaller 生成可执行程序

发布时间:2026/9/21 14:03:53

Kivy Windows 应用打包实战:基于 PyInstaller 生成可执行程序 Kivy Windows 应用打包实战基于 PyInstaller 生成可执行程序【免费下载链接】kivyOpen source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS项目地址: https://gitcode.com/gh_mirrors/ki/kivy本文是 Kivy 官方打包指南中 Windows 平台部分的深度实战讲解完整覆盖从环境准备、基础目录型打包、单文件打包、数据文件捆绑到 GStreamer 视频应用打包的完整流程并结合本仓库源码kivy/tools/packaging/pyinstaller_hooks/剖析 PyInstaller hook 的工作机制与瘦身方法。读完本文你将能够独立把一个 Kivy 应用含自定义图标、KV 文件、图片资源甚至视频依赖打包为可在 Windows 上双击运行的.exe程序。适用范围与前置条件按官方文档说明本文档仅适用于Kivy 1.9.1 及以上版本且打包过程只能在 Windows 操作系统内完成无法跨平台交叉打包 Windows 程序。文档中给出的流程已在 Windows 上使用 Kivywheels安装方式验证通过其他安装方式如源码编译、conda 等的处理见文末「备选安装方式」一节。打包产物是 32 位还是 64 位取决于你运行打包命令的Python 解释器位数与 Kivy 本身无关。因此如需 64 位程序请使用 64 位 Python 执行打包。环境准备依赖清单打包前需要准备两个核心依赖最新版 Kivy按官方 Windows 安装指南见 doc/sources/gettingstarted/installation.rst以 wheels 方式安装。wheels 方式会一并安装kivy_deps系列二进制依赖包sdl3、glew等这些包暴露的dep_bins属性是后续 spec 文件配置的关键。PyInstaller 3.1通过pip install --upgrade pyinstaller安装。3.1 版本起 PyInstaller 官方自带 Kivy 的 hook使得基础打包开箱即用。PyInstaller 默认 hook 是什么PyInstaller 通过静态分析只能找到直接import的模块而 Kivy 大量核心功能video、audio、spelling、window 等是间接导入的——Kivy 在运行时才根据平台和配置动态加载对应的 provider。默认 hook 的作用就是把这些间接依赖补充进打包清单让 PyInstaller 不至于漏掉它们。默认 hook 会添加全部核心模块audio、video、spelling 等及其依赖这保证了开箱即用的正确性但代价是产物偏大。如果你希望裁剪体积或默认 hook 未被安装就需要使用 Kivy 提供的备选 hook见下文「覆盖默认 hook」一节。无论采用哪种 hookGStreamer 等原生 DLL 都仍需通过 spec 中的Tree()手动打包见「打包视频应用」。打包一个简单应用以 touchtracer 为例官方指南以touchtracer示例项目为演示对象。该示例位于仓库 examples/demo/touchtracer 目录主入口为 main.py并依赖touchtracer.kv、particle.png、icon.png等资源文件。在 wheels 安装方式下这些示例位于python\share\kivy-examples从 GitHub 源码安装时则位于kivy\examples。下文统一用examples-path指代示例根目录。第一步生成初始 spec在命令行确保python可用后创建一个用于存放打包产物的文件夹例如TouchApp进入该目录后执行python -m PyInstaller --name touchtracer examples-path\demo\touchtracer\main.py这条命令会基于main.py生成touchtracer.spec规格文件。若希望给可执行文件附加自定义图标可先将icon.png转换为.ico格式如使用 ConvertICO 等在线工具放入 touchtracer 目录后再带上--icon参数python -m PyInstaller --name touchtracer --icon examples-path\demo\touchtracer\icon.ico examples-path\demo\touchtracer\main.py其余 PyInstaller 选项请查阅 PyInstaller 官方手册。第二步编辑 spec 加入 Kivy 依赖生成的touchtracer.spec位于TouchApp目录。用编辑器打开在spec 文件开头加入假设使用默认的 SDL3 后端from kivy_deps import sdl3, glew随后找到COLLECT()调用为其添加 touchtracer 的数据文件touchtracer.kv、particle.png等。做法是新增一个Tree()对象指向示例目录——Tree()会递归搜索并打包该目录下的所有文件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)], stripFalse, upxTrue, nametouchtracer)关键点在于*[Tree(p) for p in (sdl3.dep_bins glew.dep_bins)]它遍历kivy_deps.sdl3与kivy_deps.glew两个包的dep_bins路径列表把 SDL3、GLEW 所需的全部 DLL 一并加入产物。这与仓库自带测试 spec 的写法完全一致见 kivy/tests/pyinstaller/simple_widget/main.spec。第三步构建并定位产物在TouchApp目录执行python -m PyInstaller touchtracer.spec构建完成后编译产物位于TouchApp\dist\touchtracer目录其中包含可执行的touchtracer.exe及配套资源文件。整个dist\touchtracer文件夹即可整体分发。单文件应用--onefile若希望分发时只有一个独立可执行文件可在上述流程基础上改用--onefile模式python -m PyInstaller --onefile --name touchtracer examples-path\demo\touchtracer\main.py此时生成的 spec 中依赖与数据需要加到EXE()命令的参数里而不是COLLECT()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)], upxTrue, nametouchtracer)按相同方式构建python -m PyInstaller touchtracer.spec后产物位于TouchApp\dist目录且只有一个可执行文件。捆绑数据文件处理临时解包目录单文件模式下程序运行时会先把自身解压到系统临时目录Kivy 的资源查找机制默认不知道这个临时位置导致图片、数据库等外部数据文件无法被定位。官方给出了两处修改1. 主程序加入资源路径在main.py中补充导入若尚未存在import os, sys from kivy.resources import resource_add_path, resource_find并在入口处判断sys._MEIPASSPyInstaller 注入的临时解包路径变量if __name__ __main__: if hasattr(sys, _MEIPASS): resource_add_path(os.path.join(sys._MEIPASS)) TouchtracerApp().run()resource_add_path与resource_find是 Kivy 资源管理机制的核心 API定义于 kivy/resources.py。Kivy 在查找图片、KV 文件等资源时会按顺序遍历内部的resource_paths列表默认包含当前目录、脚本所在目录、Kivy 安装目录等resource_add_path就是向这个列表追加搜索路径从而让 Kivy 能感知到 PyInstaller 的解包目录。2. 按 PyInstaller 文档包含数据文件数据文件的包含方式遵循 PyInstaller 官方文档通过--add-data或 spec 中datas/Tree()配置随后按前述流程重新打包即可。打包视频应用加入 GStreamerKivy 的视频播放默认依赖 GStreamer官方指南以 examples/widgets/videoplayer.py 为例演示。创建VideoPlayer文件夹并进入后执行python -m PyInstaller --name gstvideo examples-path\widgets\videoplayer.py同样编辑生成的gstvideo.spec这次在开头同时引入 gstreamer 依赖from kivy_deps import sdl3, glew, gstreamer在COLLECT()中加入视频资源目录的Tree()并把 gstreamer 的dep_bins追加进依赖列表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)], stripFalse, upxTrue, namegstvideo)构建python -m PyInstaller gstvideo.spec后gstvideo.exe位于VideoPlayer\dist\gstvideo运行即可播放视频。值得一提的是仓库的 video_widget 测试 spec 展示了更健壮的依赖收集写法对ffpyplayer、gstreamer这类可选依赖使用try/except ImportError包裹未安装时自动跳过避免打包脚本在缺少可选依赖的环境下直接报错。覆盖默认 hook按需裁剪、缩小体积默认 hook 会把 Kivy所有核心 provider 打入包内。若未安装默认 hook或希望裁剪掉不需要的模块例如完全不用音视频以缩小体积可以使用 Kivy 自带的备选 hook 机制相关实现全部位于 kivy/tools/packaging/pyinstaller_hookshookspath()返回备选 hook 所在目录即本仓库的pyinstaller_hooks目录。该备选 hookhook-kivy.py不默认包含任何 provider仅加入 Factory 注册模块与基础 kivy 模块。runtime_hooks()返回运行时 hook 路径pyi_rth_kivy.py。它负责在程序启动时设置KIVY_DATA_DIR、KIVY_MODULES_DIR、GST_PLUGIN_PATH、GST_REGISTRY等环境变量指向sys._MEIPASS下的kivy_install目录。只有当 PyInstaller 未自带默认 hook 时才必须显式提供覆盖默认 hook 场景下通常无需修改它。get_deps_all()返回hiddenimports、excludes、binaries三个键的字典等价于默认 hook 的完整行为——收集kivy.core下所有可能的 provider可用于生成一份完整清单。get_deps_minimal(**kwargs)只收集运行时实际加载的 provider并支持按核心模块精确裁剪详见下文。在 spec 中启用备选 hook先在 spec 开头导入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], ... hookspathhookspath(), runtime_hooksruntime_hooks(), ... **get_deps_all())上述写法等价于默认 hook 的全部内容若想排除音频与视频 provider、其余核心模块按运行时实际加载收集则改为a Analysis([examples-path\\demo\\touchtracer\\main.py], ... hookspathhookspath(), runtime_hooksruntime_hooks(), ... **get_deps_minimal(videoNone, audioNone))get_deps_minimal接受的核心模块关键字为audio, camera, clipboard, image, spelling, text, video, window各取值的含义见init.py 的文档字符串取值行为True默认可省略包含当前系统加载该核心模块时实际导入的 providerNone完全排除该核心模块由于exclude_ignored默认开启还会把它加入excludes防止被 PyInstaller 意外捎带进去字符串或字符串列表只包含指定 provider如audio[gstplayer, ffpyplayer]、spellingenchantget_deps_minimal返回的字典同样含hiddenimports、excludes、binaries三键可直接以**展开传给Analysis。其中binaries仅在包含gstplayer时会收集 GStreamer 插件与依赖库其余情况若exclude_ignored开启还会把kivy.lib.gstplayer加入排除列表进一步防止冗余打包。生成可手编辑的完整 hook 清单pyinstaller_hooks还附带一个 hook 生成器可产出一份逐行列出全部 provider 模块的 hook 文件随后手动注释掉不需要的模块即可实现最细粒度的裁剪python -m kivy.tools.packaging.pyinstaller_hooks hook filenamefilename为要生成的 hook 文件路径省略时则把内容打印到终端。生成逻辑见 kivy/tools/packaging/pyinstaller_hooks/main.py它基于get_deps_all()[hiddenimports]输出并拼接在备选 hook-kivy.py 的hiddenimports列表之后。将该文件放到--additional-hooks-dir指定目录即可覆盖默认 hook 的hiddenimports/excludedimports全局变量。备选安装方式非 wheels上述示例中的*[Tree(p) for p in (sdl3.dep_bins glew.dep_bins gstreamer.dep_bins)]依赖kivy_deps系列 wheels 包。若 Kivy 不是通过 wheels 安装的这些包不存在from kivy_deps import sdl3会直接导入失败。此时需要手动定位 SDL3、GLEW、GStreamer 等原生 DLL 的实际安装位置将这些目录以同样的方式传给Tree()例如Tree(C:\\path\\to\\sdl3\\bin)其余 spec 配置流程不变。验证与调试建议仓库在 kivy/tests/pyinstaller 下维护了simple_widget与video_widget两套可运行的 PyInstaller 打包测试用例其 spec 是上文所有配置的最佳实践参照可直接作为模板使用。打包完成后若程序启动即崩溃优先检查Tree()是否覆盖了 KV 文件与图片等数据资源、dep_bins的 DLL 是否齐全、是否启用了备选 hook 却漏掉了运行时实际使用的 provider。单文件模式运行时报找不到资源请确认主程序中已按「捆绑数据文件」一节调用resource_add_path(sys._MEIPASS)。视频应用报 GStreamer 相关错误时可检查pyi_rth_kivy.py注入的GST_PLUGIN_PATH与GST_REGISTRY是否指向正确解包路径必要时用环境变量显式指定GST_PLUGIN_PATH指向插件目录。通过以上流程从最简单的目录型分发、单文件 exe到带数据资源与 GStreamer 视频依赖的完整应用你都能基于 PyInstaller 与 Kivy 自带的 hook 体系在 Windows 上稳定产出可分发程序并按需裁剪核心模块以控制体积。【免费下载链接】kivyOpen source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS项目地址: https://gitcode.com/gh_mirrors/ki/kivy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/21 13:58:53

AI前端面试核心:SSE流式处理与TypeScript类型安全实战

1. 这不是鸡汤,是9月AI前端面试现场的真实战报“最后提醒一次,9月的AI前端面试不用太老实”——这句话不是标题党,是我上周连续面了7家一线大厂和明星创业公司后,在凌晨两点改完第3版简历时写在备忘录里的第一行字。它背后没有情绪…

2026/9/21 13:58:53

iPhone/iPad上跑通AI Agent:混合架构与MCP工具调用实战

上个月,我把一个几乎完整的 AI Agent 跑在了 iPhone 和 iPad 上。这里说的“完整”,不是像聊天助手那样能一问一答就完事,而是它真的能自己调用工具、查天气、写备忘录、整理周报,还带长期记忆。折腾这个项目的起因很简单&#xf…

2026/9/21 13:58:53

在 iPhone 上跑通几乎完整的 AI Agent:架构、踩坑与实测

"我把一个几乎完整的 AI Agent,跑在了 iPhone 和 iPad 上"——这句话我憋了三个月才敢拿出来说。最开始我对这件事的判断是"套个壳、接个 API 不就完了?"可真把一个能感知、会规划、能调用工具、有长期记忆的 Agent 部署到实机上&am…

2026/9/21 15:24:03

Win32 Disk Imager在Windows 11下备份树莓派SD卡的底层原理与实战

1. 为什么在Windows 11上用Win32 Disk Imager备份树莓派SD卡,至今仍是硬核玩家的首选方案我从树莓派B时代就开始折腾嵌入式系统,手头积压了二十多张不同用途的SD卡——有跑Home Assistant的家庭中枢、有部署OpenCV做视觉识别的实验卡、还有给学生上课用的…

2026/9/21 15:24:03

MiMo-V2 全家桶跑 Agent:Key 用 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 3:28:31

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/21 3:33:19

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/21 0:02:23

OpenResearch:构建可复现的开放式研究工作流

第一次看到“OpenResearch”这个名字,我脑子里冒出的不是某个具体软件,而更像一种研究方式的宣言:开放、可复现、可验证。这三件事放在一起,其实比大多数人想象中难得多。过去几年我一直在折腾自己的研究工作流,从纯纸…

2026/9/20 4:54:47

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/20 5:01:23

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/21 10:29:02

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码