Flet 0.86 Android 打包迁移指南:理解 zip 化 site-packages 与 `extract_packages` 机制
发布时间:2026/9/24 14:41:52 锦皓数字建站

前端跨平台桌面应用移动开发【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址https://gitcode.com/gh_mirrors/fl/flet点击查看免费下载Flet 0.86.0 对 Android 应用的 Python 代码打包方式做了根本性调整原生扩展模块.so改为直接从 APK 内存映射加载纯 Python 代码则随stdlib.zip/sitepackages.zip就地导入不再按 ABI 重复打包或首次启动时全量解压。这一改动让 APK 显著变小但也让少数依赖__file__/pkg_resources读取数据文件的包在设备上运行时崩溃。本文以 android-extract-packages.md 为骨架结合 Android 打包官方文档 与 flet-cli 源码 的实现细节完整讲解新打包机制的原理、故障症状、extract_packages的配置方法与优先级规则帮助你完成迁移并定位解决 zip 内数据文件读取失败的问题。背景0.86.0 起 Android 打包方式的三个变化自 Flet 0.86.0 起flet build apk/flet build aab生成的应用在 Python 代码的组织方式上发生了如下变化原生扩展模块.so内存映射加载.so文件不再被解压到磁盘而是从已安装的 APK 中直接内存映射memory-mapped加载。纯 Python 代码以 stored zip 资产发布标准库与 site-packages 分别被打包进stdlib.zip与sitepackages.zip运行时通过 Python 内置的zipimport就地导入不再按 ABI 重复复制一份也不再在首次启动时解压全部内容。移除旧 workaround 的需求由于不再从 APK 解压原生库与 Python 代码原先为兼容这些行为而配置的useLegacyPackaging/keepDebugSymbols之类的规避手段已不再需要。这一改动带来的直接收益是APK 体积显著缩小。绝大多数包从 zip 中导入是完全透明的用户无感知只有少数通过真实文件系统路径定位打包数据文件的包需要特殊处理这正是本文后续要讲解的extract_packages。关于现代打包modern与遗留打包legacyuseLegacyPackaging true两种模式下原生库存储方式的详细对比包括原始 APK 体积、Play Store 下载体积、设备安装体积与启动速度的权衡表可查阅 Native library packaging (modern vs legacy) 一节。影响范围仅限 Android此变更只影响 Android 目标macOS、iOS、Windows、Linux 上site-packages 仍然以未压缩的目录形式发布行为不变WebPyodide目标不受影响如果应用只面向桌面、iOS 或 Web或者 Android 应用的依赖全部是 zip 安全的这是常见情况则此变更纯粹是体积优化无需任何操作。为什么部分包必须解压__file__与 zip 的不兼容性从 zip 导入对绝大多数包是透明的原因是它们定位代码和数据文件都遵循 Python 的标准导入机制。但有一类包存在例外它们通过真实文件系统路径定位打包的数据文件典型做法包括用__file__拼接数据文件路径后直接open()用pkg_resources读取元数据或数据资源。这两种方式在包被导入时__file__指向的是sitepackages.zip内部路径例如.../sitepackages.zip/matplotlib/...而普通open()无法在 zip 压缩包内部打开文件于是运行时抛错。相比之下zip 安全的importlib.resourcesAPI 可以在 zip 内解析资源因此像flet、certifi这类通过importlib.resources读取数据的包不需要加入extract_packages。从源码注释可以印证这一设计的意图。在 build_base.py 中android_extract_packages被描述为path-hungry packages shipped extracted to disk instead of inside the zip依赖路径的包改为解压到磁盘而非留在 zip 内其场景正是packages that read bundled data via__file__/pkg_resourcesrather thanimportlib.resources见 CLI 参数定义处 的 help 文本。解压语义当你把某个包加入extract_packages后Flet 会将该包对应的顶层目录及其下所有内容解压到应用的文件目录files directory而不是留在sitepackages.zip内。这样__file__相对路径的读取就会重新指向真实的磁盘文件恢复正常工作。症状构建成功但设备上运行时崩溃此问题的典型特征是构建阶段一切正常构建过程只负责打包不负责执行应用代码但应用安装到设备后在导入或首次使用该包时报错。错误堆栈中通常会出现以sitepackages.zip或stdlib.zip作为路径目录组件的路径例如以matplotlib为例FileNotFoundError: [Errno 2] No such file or directory: /data/user/0/applicationId/files/.../sitepackages.zip/matplotlib/mpl-data/matplotlibrc路径中的applicationId对应你应用的 Android application ID。除了FileNotFoundErrorNotADirectoryError或OSError带有类似的sitepackages.zip/...路径同样是常见信号——说明该包从__file__计算出了数据路径却把 zip 内部条目当成了普通文件来读取。迁移指南把失败的包加入extract_packages遇到上述崩溃时迁移动作只有一个把失败包的导入名加入配置。有两种等价方式。方式一在pyproject.toml中配置[tool.flet.android] extract_packages [matplotlib, sklearn]方式二通过命令行参数传递flet build apk --android-extract-packages matplotlib sklearn命令行参数--android-extract-packages支持nargs可一次传入多个包名见 参数定义。关键条目是导入名不是发行名每个条目必须是该包的import name导入名——也就是它在 site-packages 下的顶层目录名——而不是 PyPI 发行名distribution name发行名PyPI导入名应填写的条目scikit-learnsklearnopencv-pythoncv2matplotlibmatplotlib例如填写sklearn而非scikit-learn填写cv2而非opencv-python。配置优先级与源码实现extract_packages的取值遵循严格的优先级顺序resolution orderCLI 参数--android-extract-packages平台配置[tool.flet.android].extract_packages全局配置[tool.flet].extract_packages。也就是说只要命令行提供了参数它就覆盖pyproject.toml中的所有配置[tool.flet.android]下的配置又优先于[tool.flet]下的全局配置。这一顺序在 Android 打包文档的 Resolution order 小节 中有明确说明。从源码可以进一步看到它如何落地。在 build_base.py 中仅当self.package_platform Android时才处理该选项印证了仅影响 Android的约束用户列表依次尝试options.android_extract_packages→tool.flet.android.extract_packages→tool.flet.extract_packages取第一个非空值最终通过list(dict.fromkeys(ANDROID_DEFAULT_EXTRACT_PACKAGES user_extract_packages))合并内置默认集与用户列表并利用dict.fromkeys去重。其中ANDROID_DEFAULT_EXTRACT_PACKAGES定义于 build_base.py 第 78 行当前为list[str] []空列表即仓库当前版本中内置默认集为空实际生效条目完全由用户配置决定从代码注释看其设计意图是内置一套覆盖常见坏包的默认集用户列表CLI / pyproject在其基础上合并。该列表随后通过环境变量传递给serious_python_android的 Gradle 构建步骤代码注释指出该选项Consumed by the serious_python_android Gradle split duringflutter buildso the env var is set on build_env。通配符与 dist-info 目录条目本质上是相对于 site-packages 的路径匹配该路径及其下所有内容。条目中还可以使用*和?通配符它们针对顶层目录名进行匹配[tool.flet.android] extract_packages [somepackage*]通配符形式还能顺带解压同级的somepackage-version.dist-info/目录。这对于通过pkg_resources读取元数据或数据文件的包尤为有用——因为pkg_resources有时需要访问dist-info目录中的元数据。已知受影响的包列表截至当前文档以下包已知需要解压才能在 Android 上正常工作表格来源Affected packages包PyPI应填条目原因matplotlibmatplotlib通过__file__相对路径读取mpl-data字体、matplotlibrcscikit-learnsklearn通过__file__相对路径加载打包的数据文件opencv-pythoncv2通过__file__相对路径解析配置文件并加载原生扩展astropyastropy导入时通过__file__读取astropy/CITATIONthincthinc导入时通过__file__读取thinc/backends/_custom_kernels.cuspacyspacy, thinc加载时导入thinc并通过__file__读取自身语言数据两者都要列出注意spacy一行它依赖thinc因此需要同时列出spacy与thinc两个条目。排障建议与补充如果某个依赖在设备上报出前述 zip 路径错误但它不在上表中将该包加入extract_packages后重新构建验证加入后 Flet 会将其解压到应用文件目录__file__相对读取即可恢复可以在 Flet 官方 discussions 中报告该包或提交 PR 把它补充到已知包列表中帮助后续用户见 Android 打包文档 中的相关说明。此外若你的排障涉及原生库加载问题而非纯 Python 数据文件注意extract_packages与遗留打包legacy packaging解决的是两类不同问题前者针对 zip 内数据文件的读取后者针对.so在 APK 内的存储与解压方式。遗留打包只是改变了原生库的存储与加载方式并不能让不兼容的库变得可用也不应作为extract_packages的替代方案。时间线变更版本0.86.0延伸阅读Android packaging: extract packages官方维护的功能文档含通配符行为与完整示例Native library packaging: modern vs legacyflet buildCLI 参考Breaking changes and deprecations index列出各版本迁移指南flet-cli 对extract_packages的完整实现build_base.py赞分享前端跨平台桌面应用移动开发【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址https://gitcode.com/gh_mirrors/fl/flet点击查看免费下载相关推荐Flet 0.86 起 flet build 默认将应用与依赖包编译为 .pyc机制解读与迁移指南Flet 0.86 起 flet build 默认将应用与依赖包编译为 .pyc 机制解读与迁移指南 自 Flet 0.86.0 起 flet build前端跨平台桌面应用移动开发Flet 0.86 发布详解dart-bridge 进程内通信、全新 Android 打包与 Python 3.14 支持Flet 0.86 发布详解dart bridge 进程内通信、全新 Android 打包与 Python 3.14 支持 Flet 0.86.0 是通往 1前端跨平台桌面应用移动开发Flet 应用分发打包指南从 flet build 看懂全平台构建机制Flet 应用分发打包指南从 flet build 看懂全平台构建机制 flet build 是 Flet CLI 提供的一键打包命令它能将 Python前端跨平台桌面应用移动开发上一篇JoyAI-Image-Edit-Plus-Diffusers终极AI图像编辑增强工具完全指南下一篇Data Science for Beginners quiz-appVue 测验应用的多语言内容组织、构建与 Azure 部署实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。