Skip to content

Android:site-packages 以压缩形式分发;部分包需要 extract_packages ​

INFO

本指南以 Flet 0.86.0 为准,内容是最准确的。后续版本可能会新增 API 或增加额外的迁移路径。

破坏性变更与废弃索引列出了为每个版本编写的指南。

概述 ​

Flet 0.86.0 改变了 Python 代码打包进 Android 应用(flet build apk / aab)的方式:

  • 原生扩展模块(.so 文件)被直接从 APK 以内存映射方式加载——不解压到磁盘。
  • 纯 Python 代码——标准库和你的 site-packages——以存储型 zip 资产 (stdlib.zip、sitepackages.zip)分发,并通过 zipimport 就地导入,因此它不再按 ABI 各自复制,也不会在首次启动时解包。

这让 APK 显著变小,并消除了对 useLegacyPackaging / keepDebugSymbols 变通手段的需求。从 zip 导入对大多数包是透明的。

有些包仍然通过真实的文件系统路径去定位打包的数据文件,通常是使用 __file__ 或 pkg_resources,而非 zip 安全的 importlib.resources。这些包必须列在 extract_packages 中,以便它们以解包形式分发到磁盘。

这仅影响 Android。在 macOS、iOS、Windows 和 Linux 上,site-packages 以未打包形式分发;Web(Pyodide)不变。

关于该功能的完整文档(包括示例、通配符行为,以及当前已知受影响包的列表),请参阅 Android 打包:解包包。

症状 ​

构建会成功,但应用在设备上导入该包或首次使用时崩溃或报错。回溯信息通常包含 sitepackages.zip 或 stdlib.zip 作为目录组成部分的路径,例如:

bash
FileNotFoundError: [Errno 2] No such file or directory:
  '/data/user/0/<applicationId>/files/.../sitepackages.zip/matplotlib/mpl-data/matplotlibrc'

NotADirectoryError 或带有类似 sitepackages.zip/... 路径的 OSError 也是一个常见信号,说明该包从 __file__ 计算出了数据路径,并试图把它当作普通文件读取。

迁移指南 ​

把出问题的包的导入名加入你的 pyproject.toml:

toml
[tool.flet.android]
extract_packages = ["matplotlib", "sklearn"]

或者在命令行传入:

bash
flet build apk --android-extract-packages matplotlib sklearn

一个条目是包的导入名——它在 site-packages 下的顶层目录名——而不是 PyPI 的发行名:sklearn 而非 scikit-learn;cv2 而非 opencv-python。

Flet 会把列出的包目录及其下的所有内容解包到应用的 files 目录,于是 __file__ 相对读取就能再次工作。

无需改动的情况 ​

  • 仅面向桌面、iOS 或 Web 的应用。
  • 依赖项全部 zip 安全(常见情况)的 Android 应用——这样变更纯粹是体积上的胜利。

时间线 ​

  • 变更于:0.86.0

参考 ​


关注我,学习大模型、大数据、Python等热门技术。