Skip to content

发布 Flet 应用 ​

Flet CLI 提供 flet build 命令,用于将 Flet 应用打包成可独立运行的可执行文件或可分发的安装包。

另一种选择:flet pack

对于桌面平台,也支持基于 PyInstaller 的打包方式——参见 flet pack。

前置条件 ​

平台矩阵 ​

使用下面的矩阵来判断:为了针对某个平台进行构建,可以在哪个操作系统上运行 flet build:

运行于apk/aabipa/ios-simulatormacoslinuxwindowsweb
macOS✅✅✅✅
Windows✅✅ (WSL)✅✅
Linux✅✅✅

Flutter SDK ​

Flutter 是构建任意平台的 Flet 应用所必需的。

如果系统中 PATH 里还没有可用的 Flutter SDK 最低要求版本,它会在首次构建过程中自动下载并安装(到 $HOME/flutter/{version} 目录)。

提示

推荐的(即最低要求的)Flutter SDK 版本取决于所安装或使用的 Flet 版本。

可以通过以下命令之一查看:

bash
flet --version
bash
uv run python -c "import flet.version; print(flet.version.flutter_version)"

或者使用下面的 Python 代码片段:

python
import flet.version
print(flet.version.flutter_version)

项目结构 ​

flet build 命令假定你的 Flet 项目具有如下最小结构:

text
README.md
pyproject.toml [^1]
src
    assets [^2]
        icon.png
    main.py [^3]
  1. 作为你的应用的主配置文件。 它包含元数据、依赖和构建设置。 至少,dependencies 部分应当指定 flet 包。

示例

下面是一个 `pyproject.toml` 文件示例:
```toml title="pyproject.toml"
[project]
name = "example"
version = "0.1.0"
description = "An Example."
readme = "README.md"
requires-python = ">=3.14"
authors = [{ name = "Me", email = "me@example.com" }]
dependencies = [
  "flet"
]

[tool.flet]
org = "com.mycompany"
product = "My App"
company = "My Company"
copyright = "Copyright (C) 2025 by My Company"

[tool.flet.app]
path = "src"
```
  1. 一个可选的目录,用于存放应用静态资源 (图片、声音、文本以及应用所需的其他文件),以及用于包 图标 和 启动画面 的图片。 [^3]: 你的 Flet 应用的主 入口点。它通常包含对 ft.run() 的调用。

提示

要快速搭建一个结构正确的项目,可使用 flet create 命令:

bash
flet create <project-name>

其中 <project-name> 是你的项目目录名。

使用 requirements.txt 代替 pyproject.toml

你也可以用 requirements.txt 文件(而不是 pyproject.toml)来指定依赖。

这种情况下有两点需要注意:

  • 如果两个文件都存在,flet build 会忽略 requirements.txt。
  • 不要使用 pip freeze > requirements.txt 来生成该文件或往里面塞依赖, 因为它可能包含与目标平台不兼容的包。相反,应当手工挑选并只加入 应用所需的直接依赖(包括 flet)。

选择 Python 版本 ​

flet build 与 flet publish 会把某个特定的 Python 发行版打包进你的应用。 支持的版本及对应的 CPython / Pyodide 产物如下:

简写CPython 运行时Pyodide(web)状态
3.143.14.7314.0.6default
3.133.13.150.29.4stable
3.123.12.140.27.7stable

版本按以下顺序解析:

  1. --python-version X.Y——显式覆盖。必须匹配某个受支持的简写版本 (例如 flet build apk --python-version 3.13)。
  2. pyproject.toml 中的 [project].requires-python——按 PEP 440 说明符解析;满足该说明符的最高受支持简写版本胜出。 requires-python = ">=3.13,<3.14" 解析为 3.13; requires-python = ">=3.13" 解析为 3.14。 [^3]: 默认——在上方表格中标记为 default 的版本。

如果命令行参数和 requires-python 都没有选出受支持的版本 (例如 requires-python = ">=3.20"),构建会失败并给出清晰的错误, 列出你可以选择的版本。

对于 web 构建(flet build web / flet publish),对应的 Pyodide 运行时会被下载到构建输出中,并在首次使用时缓存到 ~/.flet/pyodide/<version>/ 下,因此后续构建会复用它。原本内置在 构建模板里的旧版 0.27.5 包已移除,改为这种每次构建、带版本的下载方式。

预发布版 Python(3.15 等)

要打包预发布版 Python,需显式指定名称——--python-version 3.15 或 requires-python = "==3.15.*"。这里没有独立的 --pre 标志。 flet publish 上的 --pre 标志是一个 不同的、互不相关的选项,用于在运行时允许 micropip 安装预发布版 Python 包。

工作原理 ​

当你运行 flet build <target_platform> 时,流程如下:

  1. 根据 模板 在 {flet_app_directory}/build/flutter 创建一个 Flutter 项目。 该 Flutter 应用把你的 Python 应用作为静态资源嵌入,并使用 flet 与 serious_python 来运行应用并渲染界面。 该项目会被缓存并在多次构建之间复用,以实现快速迭代; 运行 flet clean 可删除 build 目录并强制重新构建。
  2. 将自定义的 图标 和 启动画面图片 从 assets 复制到 Flutter 项目中,然后生成:
  3. 使用 serious_python package 打包 Python 应用:
  4. 运行 flutter build 生成 可执行文件或安装包。 [^5]: 将第 4 步的构建输出复制到 输出目录。

构建后的应用如何终止 ​

构建后的 Flet 应用会立即终止。Python 的 atexit 处理器、__del__ 终结器、 C++ 静态析构函数,以及尚未到达操作系统的缓冲写入,都不保证会执行。在退出之前 就把重要的内容持久化保存,而不要依赖关闭时的清理工作。

这一点既适用于用户关闭应用(桌面端),也适用于你的代码调用 sys.exit()(所有平台)。

原因在于,你的 Python 代码运行在独立于 Flutter 的线程上。正常的进程退出会执行 每一个已加载库的拆卸工作——包括 matplotlib、numpy、Pillow 等包导入的 C 扩展模块——而此时该线程可能仍在这些模块内部执行。结果就是退出时发生段错误, 即使应用已经完成工作,操作系统也会将其报告为崩溃。跳过拆卸可以彻底消除这个故障, 代价就是上面提到的那些保证不再成立。

如果你需要让清理工作运行,请在退出之前显式执行。当你自己的代码结束应用时,先把工作做完:

python
async def quit(e):
    await save_my_state()   # 先完成你自己的工作
    sys.exit(0)

在桌面端,用户也可以关闭窗口,这是由操作系统发起的——你的代码永远不会被询问。 为了能抢先执行,可以通过 [Window.prevent_close][flet.Window.prevent_close] 拦截关闭信号,并在你完成后再自行销毁窗口:

python
import flet as ft


async def main(page: ft.Page):
    async def handle_window_event(e: ft.WindowEvent):
        if e.type == ft.WindowEventType.CLOSE:
            await save_my_state()          # 在进程消失之前运行
            await page.window.destroy()

    page.window.prevent_close = True
    page.window.on_event = handle_window_event

不设 prevent_close 的话,关闭窗口会直接走到进程终止,你的任何代码都不会运行。 让处理器保持轻量:它会拖住应用的退出,如果退出耗时过久,操作系统可能会失去耐心。

配置选项 ​

占位符

本篇文档中统一使用以下占位符:

  • <target_platform>——取值之一:apk、aab、ipa、ios-simulator、web、macos、windows、linux。
  • <PLATFORM>——[tool.flet.<PLATFORM>] 下的配置命名空间;取值之一:android(对应 apk 与 aab 目标)、ios(对应 ipa 与 ios-simulator 目标)、web、macos、windows、linux。
  • <python_app_path>——传给 flet build 的路径(默认为当前目录)。
  • <flet_app_directory>——<python_app_path> 解析出的项目根目录;pyproject.toml 与 requirements.txt 从这里读取。
  • <flet_version>——正在使用的 Flet 版本。可通过 flet --version 或 uv run python -c "import flet; print(flet.__version__)" 查看。

平台级覆盖(Platform-specific overrides)

当某个设置既可在 [tool.flet] 下、又可在 [tool.flet.<PLATFORM>] 下配置时, 只要平台级取值存在,即以平台级为准。对于列表与表格类设置(例如 app.exclude、app.include、source_packages、dev_packages、target_arch、 cleanup.app_files、cleanup.package_files 与 flutter.build_args), 空值会清除该平台对应的全局取值:

toml
[tool.flet]
source_packages = ["numpy"]

[tool.flet.ios]
source_packages = []    # iOS 平台不进行源码构建

理解 pyproject.toml 的结构

Flet 将 pyproject.toml 作为嵌套字典加载,并使用 点分隔路径来查找设置(例如 tool.flet.web.base_url)。

下面两种形式是等价的,会解析为同一个键值对:

  • 形式 1(本篇文档中将使用/优先采用)

    toml
    [tool.flet.section]
    key = "value"
  • 形式 2

    toml
    [tool.flet]
    section.key = "value"

但它们与下面这种写法不同、也不应混淆("带引号的键"是字面量,不会创建嵌套):

toml
[tool.flet]
"section.key" = "value"

App path(应用路径) ​

定义你的 Python 应用在 <python_app_path> 内的根目录。 Flet 会相对该目录查找 入口点、assets 目录,以及 排除路径。

解析顺序 ​

其值按以下优先级顺序确定:

  1. [tool.flet.app].path
  2. <python_app_path>

path 是相对 <python_app_path> 解析的。

示例 ​

pyproject.toml

toml
[tool.flet.app]
path = "src"

入口点 ​

这是启动你的应用、并包含对 flet.run() 或 flet.render() 调用的 Python 模块。Flet 使用该模块的 stem(去扩展名部分), 并在你的 应用路径 中查找 <module>.py。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --module-name
  2. [tool.flet.app].module
  3. "main"(入口文件为 main.py)

其值可以是 <module> 或 <module>.py;两者解析到同一个 Python 模块。

示例 ​

bash
flet build <target_platform> --module-name app.py
toml
[tool.flet.app]
module = "app.py"

项目名称 ​

项目名称是 Bundle ID 及其他内部名称的基础标识符。源值会被规范化为一个安全的标识符: 转为小写、移除或折叠标点符号与空格,并将连字符转换为下划线(例如 My App 或 my-app 会变成 my_app)。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --project
  2. [project].name
  3. 项目/应用目录名

示例 ​

bash
flet build <target_platform> --project my_app
toml
[project]
name = "my_app"

产品名称 ​

显示在窗口标题、启动器标签和关于对话框中的(面向用户的)显示名称。

它不控制磁盘上的可执行文件或打包名。产物命名请使用 Artifact name。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --product
  2. [tool.flet].product
  3. --project
  4. [project].name
  5. 项目/应用目录名

示例 ​

bash
flet build <target_platform> --product "My Awesome App"
toml
[tool.flet]
product = "My Awesome App"

产物名称 ​

磁盘上可执行文件和/或应用包的名称。例如,在 Windows 上它决定 .exe 文件的名称,在 macOS 上它设置 .app 包的名称。

它不影响 Bundle ID 或包标识符。

它可以包含空格或重音符号,但在目标平台上要注意文件系统的限制。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --artifact
  2. [tool.flet.<PLATFORM>].artifact
  3. --project
  4. [project].name
  5. 项目/应用目录名

示例 ​

bash
flet build <target_platform> --artifact "My Awesome App"
toml
[tool.flet]
artifact = "My Awesome App"

组织名称 ​

平台支持

仅限 Android、iOS、 macOS 和 Linux。

反向域名表示法的组织名称,通常形如 com.mycompany。它被用作 Bundle ID 的前缀, 并用于移动端和桌面端目标的包标识符。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --org
  2. [tool.flet.<PLATFORM>].org
  3. [tool.flet].org
  4. "com.flet"

示例 ​

bash
flet build <target_platform> --org com.mycompany
toml
[tool.flet]     # 或 [tool.flet.<PLATFORM>]
org = "com.mycompany"

Bundle ID ​

平台支持

仅限 Android、iOS、 macOS 和 Linux。

应用的 Bundle ID,通常形如 "com.mycompany.my_app"。

如果没有显式指定,它会由构建模板所使用的 组织名称 和 项目名称 推导而来。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --bundle-id
  2. [tool.flet.<PLATFORM>].bundle_id
  3. [tool.flet].bundle_id

示例 ​

bash
flet build <target_platform> --bundle-id com.mycompany.my_app
toml
[tool.flet] # 或 [tool.flet.<PLATFORM>]
bundle_id = "com.mycompany.my_app"

描述 ​

平台支持

仅限 Web 和 Linux。

对应用的简短描述。在 web 构建中它会成为 <meta name="description"> 标签以及 PWA manifest 的 description;在 Linux 上 它会变成所生成 desktop entry 的 Comment, 在应用菜单中显示为提示文本。其他平台没有对应字段,会忽略它。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --description
  2. [project].description
  3. [tool.poetry].description

示例 ​

bash
flet build <target_platform> --description "Tracks your daily habits."
toml
[project]
description = "Tracks your daily habits."

公司名称 ​

平台支持

仅限 Windows 和 macOS。

显示在关于对话框和元数据(尤其是桌面端构建)中的公司名称。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --company
  2. [tool.flet].company
  3. 构建模板默认值(见 模板源)

示例 ​

bash
flet build <target_platform> --company "My Company Inc."
toml
[tool.flet]
company = "My Company Inc."

版权信息 ​

平台支持

仅限 Windows 和 macOS。

显示在关于对话框和元数据中的版权文本。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --copyright
  2. [tool.flet].copyright
  3. 构建模板默认值(见 模板源)

示例 ​

bash
flet build <target_platform> --copyright "Copyright © 2026 My Company Inc."
toml
[tool.flet]
copyright = "Copyright © 2026 My Company Inc."

版本控制 ​

Build Number(构建号) ​

用于在内部区分不同构建的整数标识符。

每次新构建都必须有一个唯一的、递增的数字; 数字越大表示构建越新。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --build-number
  2. [tool.flet].build_number
  3. 否则,使用所生成 pubspec.yaml 中的构建号 (见 模板源)。
示例 ​
bash
flet build <target_platform> --build-number 1
toml
[tool.flet]
build_number = 1

Build Version(构建版本) ​

面向用户的 x.y.z 格式版本字符串。 每次新发布时递增它,以区别于之前的版本。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --build-version
  2. [project].version
  3. [tool.poetry].version
  4. 否则,使用所生成 pubspec.yaml 中的构建版本 (见 模板源)。
示例 ​
bash
flet build <target_platform> --build-version 1.0.0
toml
[project]
version = "1.0.0"

输出目录 ​

构建输出保存到的目录。 如果该目录已存在,每次构建都会先删除再重建。

对于 web 构建,应用的 assets 目录会被复制到输出目录中。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --output(或 -o)
  2. <python_app_path>/build/<target_platform>

示例 ​

flet build

bash
flet build <target_platform> --output <path-to-output-dir>

应用依赖 ​

这些是你的 Flet 应用正常运行所依赖的 Python 包。

解析顺序 ​

其值按以下优先级顺序确定:

  • 如果存在 [tool.poetry].dependencies,则使用它;否则使用 [project].dependencies(PEP 621)。
  • 如果设置了 [tool.flet.<PLATFORM>].dependencies(其中 <PLATFORM> 对应 <target_platform>),则其值会追加到上面的列表中。
  • 如果以上结果都为空,且 <python_app_path> 中存在 requirements.txt,则使用它。
  • 如果以上结果都为空,则使用 flet==<flet_version>。

要在构建期间使用某个依赖的本地开发版本,可通过 [tool.flet].dev_packages 或 [tool.flet.<PLATFORM>].dev_packages 配置一个"包名 → 路径"的映射。

如果你的应用使用了 Flet 扩展(第三方包),请将它们列在你的 Python 依赖中,这样它们会与应用一起打包。扩展示例可见 内置扩展。

示例 ​

pyproject.toml

toml
[project]
dependencies = [
    "flet",
    "requests",
    "flet-extension1",
    "flet-extension2 @ git+https://github.com/account/flet-extension2.git",   # git 仓库
    "flet-extension3 @ file:///path/to/flet-extension3",  # 本地包
]

[tool.flet.<PLATFORM>]  # 仅当 <PLATFORM> 对应 <target_platform> 时才会被使用/追加
dependencies = [
    "dep1",
    "dep2",
]

源码包 ​

平台支持

仅限 Android、iOS 和 Web。

默认情况下,移动端和 web 的打包只安装二进制 wheel 包。使用源码包可以 允许特定依赖从 源码分发包(sdist) 安装。

这对于安装那些目标平台没有预构建 wheel 包或全平台 wheel(*-py3-none-any.whl)、 但提供了源码分发包(*.tar.gz)的纯 Python 依赖很有用。

关于纯 Python 包与非纯 Python 包的更多信息,请参阅我们关于该主题的 博客文章。

在桌面端目标上,源码安装本来就是允许的,因此该设置主要用于 Android、iOS 和 Web (仅 flet build web——而非 flet publish)。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --source-packages
  2. [tool.flet.<PLATFORM>].source_packages
  3. [tool.flet].source_packages

示例 ​

bash
flet build <target_platform> --source-packages package1 package2
toml
[tool.flet]
source_packages = ["package1", "package2"]

图标 ​

对大多数应用来说,你只需要一张图片。把它保存为 icon.png,放在应用的 assets 目录中(即上文 项目结构 中的 src/assets/icon.png)。 当你运行 flet build 时,Flet 会生成目标平台所需的图标。

为获得最佳效果,请使用:

  • 一张 1024 × 1024 像素的 PNG,足够大以覆盖每个受支持的平台。
  • 一个 透明背景,这样 Flet 才能为每个平台添加它所需的背景。
  • 填满画布的图稿,不要有额外留白。Flet 会在需要的地方为它 添加间距;源图中的留白会让小尺寸图标看起来太小。

同一张透明图片在各平台上的效果如下:

Web、Windows、LinuxiOSmacOSAndroid可遮罩的 web 图标
填满图稿的图标嵌入在 iOS 图标中的图稿带有阴影、置于 macOS 磁贴上的图稿置于圆形 Android 图标内的图稿置于可遮罩 web 图标安全区内的图稿
原始留白添加了留白与背景圆角磁贴与阴影为启动器形状留出空间为启动器形状留出空间

可遮罩的 web 图标用于浏览器安装你的应用、且启动器应用自身图标形状 (例如圆形或圆角正方形)时。

如果你不提供图标,Flet 会使用默认的 Flet 图标。

背景颜色 ​

要将透明图稿放在白色以外的颜色上,请在 pyproject.toml 中设置 icon_background:

toml
[tool.flet]
icon_background = "#1a1a2e"

Flet 会将该颜色用于 iOS 图标、macOS 磁贴、Android 的自适应图标背景, 以及 web 的可遮罩图标和 Apple 触摸图标。Favicon、常规 web 图标、 Windows 图标和 Linux 图标则保留其透明性。

你可以为某个平台单独覆盖该颜色:

toml
[tool.flet.macos]
icon_background = "#000000"

在 Android 上,显式的 adaptive_icon_background 优先于 icon_background。要显示背景色,请保持源图稿透明;完全不透明的图片会盖住它。

填充或是不透明的源图会产生什么效果 ​

Flet 会调整 icon.png 中透明图稿周围的间距,以适配每个平台。这被称为 构图(framing)。它可以在画布内缩小图稿,但不会放大图稿来消除已有的留白。

下面的示例说明了为什么一张没有额外填充的透明图片是个不错的起点:

你的源图Web、Windows、LinuxiOSAndroid
无额外留白图稿填满画布的透明源图填满图稿的图标为 iOS 适配的图稿为 Android 适配的图稿
有留白带有额外透明留白的源图保留源图留白的小图标为 iOS 适配的带留白图稿为 Android 适配的带留白图稿
不透明带有自身纯色背景的源图图稿与背景填满方形图标带有圆角 iOS 边角的图稿与背景图稿与背景裁切为 Android 圆形

使用带留白的图稿时,web、Windows 和 Linux 上会保留已有的留白。 其他平台上 Flet 仅在需要时添加更多间距。如果你的图稿本来就比目标构图小, 它就会保持那么小。

使用不透明图稿(没有透明度的图片)时,Flet 会保留你的构图,包括其背景。 平台在应用自身图标形状时仍可能隐藏边缘,因此请将 logo 和文字保持在靠近中心的位置。 当你希望设计自身的背景延伸到边缘时,可使用这种方式。

图片尺寸与格式 ​

一张 1024 × 1024 的图片已经能覆盖 Flet 生成的最大图标。更大的图片也可以使用。 更小的图片在放大时可能显得模糊;如果你的源图小于目标平台所需的最大图标, flet build 会发出警告。

优先使用 PNG。Flet 也接受 .webp、.jpg、.jpeg、.gif、.bmp、 .tif 和 .tiff。如果多个文件具有相同的基名,Flet 优先选择 PNG。 不支持 SVG;请在构建前将其导出为 PNG。

非正方形图片会被居中放置在一个正方形画布上,不会拉伸或裁剪源图。 多余的空间在生成不透明输出时用 icon_background 填充,其他情况下保持透明:

你的 1024 × 600 源图iOS、不透明 web 图标、macOS 磁贴Favicon、常规 web 图标、Windows、Linux、Android 前景
一张宽幅源图用背景色填充的多余空间保持透明的多余空间

此处背景显示为深色以让填充可见。在 Android 上,独立的背景层会透过透明空间显示出来。 Flet 会对非正方形源图发出警告;如果你想自己控制留白,请使用正方形图片。

为单一平台制作图标 ​

要使用不同的图稿或为某个平台控制留白,可在 assets 中添加一个带有 该平台名称的文件,例如 icon_macos.png。它对该平台优先于 icon.png; 其他平台仍使用 icon.png。

平台专属文件会保留你提供的留白。 Flet 仍会生成所需的图片尺寸并应用 平台处理(例如在 iOS 上移除透明性,或为 macOS 添加磁贴),但它不会自动 将你的图稿适配进平台的可见区域。

icon.png:Flet 添加留白icon_macos.png:你自行选择留白
适配进 macOS 磁贴的共享图稿填满 macOS 磁贴的平台专属图稿

在准备你自己的文件时,请使用这些尺寸与构图指南。百分比与 Flet 对透明图稿的 自动构图一致:

文件推荐尺寸图稿位置
icon_ios.png1024 × 1024位于画布宽高的中央 60% 范围内。
icon_macos.png1024 × 1024位于画布宽高的中央 68% 范围内,在 Flet 将其置于磁贴之前。
icon_android.png1024 × 1024位于居中的圆内,直径约为画布宽度的 57%。
icon_web.png1024 × 1024对于可遮罩图标,位于居中的圆内,直径为画布宽度的 80%。
icon_windows.png 或 icon_windows.ico256 × 256 或更大可填满画布。
icon_linux.png512 × 512 或更大可填满画布。

对于圆形区域,请将整个 logo 保持在圆内,包括其四角。一个能放进相同宽度 正方形的 logo 仍可能延伸到该正方形之外。

在 Android 上,请使用透明性让 icon_background 透出来。不透明的 icon_android.png 也支持,但它自身的背景会盖住该颜色。

在 web 上,icon_web.png 提供全部六个图标,包括可遮罩图标和 Apple 触摸图标。 如果透明图稿延伸到了可遮罩安全区之外,Flet 会发出警告。若要为这些图标设置 不同的留白,请直接替换其中的某个 web 图标。

直接替换某个 web 图标 ​

要只替换一个 web 图标,可在 assets 内的对应路径放一张 PNG。 例如,assets/favicon.png 会更改浏览器标签页图标。这些文件会原样替换 生成的图标,不会重新缩放或添加留白。

assets 内的路径用于显示形状
favicon.png浏览器标签页无遮罩
icons/Icon-192.png、icons/Icon-512.png已安装应用、启动画面、任务切换器无遮罩
icons/Icon-maskable-192.png、icons/Icon-maskable-512.png使用可遮罩图标的启动器由启动器决定
icons/apple-touch-icon-192.pngiOS "添加到主屏幕"圆角

在给定了像素尺寸的文件名中使用该像素尺寸。对于可遮罩图标,请使用不透明背景, 并将重要图稿保持在 安全区内:一个直径为图片宽度 80% 的居中圆。

位于安全区内的图稿有被裁剪风险的图稿
位于可遮罩安全区内的图稿延伸到可遮罩安全区之外的图稿

圆外淡化的区域可能会被启动器的形状隐藏。

启动画面 ​

平台支持

仅限 Android、iOS 和 Web。

启动画面在应用启动期间,将你的图稿显示在一种背景颜色之上。默认情况下, Flet 使用你应用 assets 目录中的 icon.png,如果你没有提供,则使用默认 Flet 图标。

要使用不同的图稿,请将其保存为 splash.png 放在 assets 中 (即上文 项目结构 中的 src/assets/splash.png)。 一张带透明背景的正方形 PNG 是个不错的起点。Flet 会将图稿居中显示在屏幕上, 并在你运行 flet build 时生成目标平台所需的图片尺寸。

启动画面背景颜色 ​

在 pyproject.toml 中设置填满屏幕的颜色。用 color 表示浅色模式, 用 dark_color 表示深色模式:

toml
[tool.flet.splash]
color = "#ffffff"
dark_color = "#222222"
bash
flet build <target_platform> --splash-color "#ffffff" --splash-dark-color "#222222"

这些也是默认颜色。要为某个平台设置不同的背景,请使用它自己的 splash 小节:

toml
[tool.flet.android.splash]
color = "#112233"
dark_color = "#080f17"

命令行选项 --splash-color 与 --splash-dark-color 优先于平台设置, 其次是共享设置,最后是默认值。

对于深色模式,还需按下方说明提供一个 深色启动画面图片。

启动画面图片 ​

使用 splash.png 作为共享图稿,splash_dark.png 作为深色模式版本。 你可以通过添加带平台名的文件来为某个平台覆盖其中之一,例如 splash_android.png 或 splash_dark_android.png。

Flet 按以下顺序选择第一张可用的图片。将 <platform> 替换为 android、ios 或 web:

模式首选次选回退
浅色splash_<platform>.pngsplash.pngicon.png,然后是默认 Flet 图标
深色splash_dark_<platform>.pngsplash_dark.png所选的浅色模式图片

支持 与应用图标相同的图片格式; 优先使用 PNG。非正方形图片会被居中放置在一个正方形画布上,并填充透明留白, 不会拉伸或裁剪源图。

在两个主题中使用相同图稿

如果你只想在深色模式下更改背景,把相同的图稿保存为 splash_dark.png 即可。 iOS 需要一张深色启动画面图片才能应用 dark_color,Android 12 也需要一张 才能应用 icon_dark_background。

尺寸与构图 ​

在 iOS、web 以及 Android 12 之前的版本中,图片以其源尺寸的四分之一显示: 一张 1024 × 1024 的图片在屏幕上占据 256 × 256 逻辑像素。 请使用更小的图片或添加透明留白,让 logo 显得更小。

Flet 对提供的启动画面图片与回退的应用图标处理方式不同:

源Flet 如何放置图稿
splash.png 或 splash_<platform>.png保留你提供的留白。
回退的 icon.png在需要时缩小透明图稿,使其适配画布宽高的中央 60% 范围内。

已有的留白会被保留;小的图稿不会被放大以填满那个 60% 区域。 Android 12 及更高版本使用固定的图标区域,并带有 额外的适配,因此源尺寸在那里不会直接控制显示大小。

不透明图稿 ​

没有透明度的图片会保留自身的背景与构图。它仍会被缩放以生成所需的图片尺寸, 但 Flet 不会为其添加本应加在透明 logo 上的留白。

在 Android 12 上,系统的圆形裁剪可能会隐藏这张图稿的边缘。请将重要细节 保持在直径约为画布宽度 三分之二 的居中圆内。当你希望配置好的启动画面 背景显示在你的 logo 周围时,请使用透明图片。

Android 启动画面如何构成 ​

屏幕背景与图稿是独立的图层。在 Android 12 之前,图稿居中显示在背景之上。 Android 12 及更高版本将其显示在一个圆形区域内,图标后面可带一个可选颜色:

屏幕背景Android 12 之前Android 12+带图标背景的 Android 12+
启动画面背景颜色居中显示在屏幕背景之上的图稿位于 Android 12 圆形图标区域内的图稿位于屏幕背景之上、带颜色圆盘的图稿
color 或 dark_color以启动画面尺寸显示的图稿为圆形裁剪适配的图稿icon_background 填充圆盘

用 color 更改整个屏幕,用 icon_background 添加上例最后所示的有色圆盘。 请选择一个与你图稿形成对比的圆盘颜色,以便 logo 保持可见。

Android 12 启动画面图标 ​

这些设置控制 Android 12 及更高版本上的启动画面图标。请将它们放在 [tool.flet.android.splash] 下,或放在 [tool.flet.splash] 下作为共享默认值:

设置默认值效果
icon_background无填充在启动画面图标后面添加背景色。
icon_dark_background与 icon_background 相同设置深色模式下的图标背景;需要一张深色启动画面图片。
icon_fit"contain"在需要时缩小透明图稿,为圆形裁剪留出空间。使用 "none" 自行控制留白。
toml
[tool.flet.android.splash]
color = "#112233"
icon_background = "#ffffff"
icon_fit = "contain"

在这里,color 填满屏幕,icon_background 在 logo 后面添加一个白色圆盘。 这个 splash 设置独立于 用于应用图标的 icon_background。

设置了图标背景时,Android 会使用较小的图标区域。Flet 会自动生成合适的画布; 如果你要手动准备适配的图稿,请参阅 Android 的启动画面尺寸。

使用 icon_fit = "none" 时,Flet 会保留你图稿的留白,并在检测到透明图稿 延伸到中央区域之外时发出警告。请将重要细节保持在中央圆内;系统可能会裁剪圆外的任何内容。

在 1.0.0 中重命名

icon_background、icon_dark_background 和 icon_fit 分别取代了 icon_bgcolor、icon_dark_bgcolor 和 android_12_fit。旧名称仍然可用。

禁用启动画面 ​

要关闭 Flet 对某个平台的启动画面自定义,请将其值设为 false:

toml
[tool.flet.splash]
android = false
ios = false
web = false
bash
flet build apk --no-android-splash
flet build ipa --no-ios-splash
flet build ios-simulator --no-ios-splash
flet build web --no-web-splash

只设置你想禁用的平台;其他平台保持启用。命令行参数 --no-android-splash、 --no-ios-splash 和 --no-web-splash 优先于 pyproject.toml 中的对应设置。

要自定义在 Flutter 启动之后、你的 Python 应用加载完成之前显示的内容, 请参阅 Boot screen。

启动加载屏幕(Boot screen) ​

启动加载屏幕填补了原生 启动画面 与你的应用第一帧之间的空隙—— 也就是 Flutter 应用已启动、但你的 Flet/Python 应用尚未就绪的这段时间。它会被告知 当前处于两个阶段中的哪一个:

  1. Preparing(准备中)——打包后的应用归档(app.zip)正在被解压到 应用数据目录(首次启动或应用包发生变化后)。该阶段仅发生在 Android 上。
  2. Starting up(启动中)——Python 运行时与你的应用正在启动,直到第一页显示 (所有平台)。如果启动失败,错误会显示在启动加载屏幕上。

启动加载屏幕始终会渲染,因此这段空隙是一块受控的背景,而不是裸露的脚手架。 默认情况下,内置的 flet 启动加载屏幕只显示一个背景色——没有转圈、也没有消息—— 直到你对其进行配置。你也可以用自己的控件完全替换它 (参见 自定义启动加载屏幕)。

选择启动加载屏幕 ​

启动加载屏幕通过 name 来寻址。默认是 flet(内置屏幕); 自定义名称由 扩展 提供。

pyproject.toml

toml
[tool.flet.boot_screen]    # 或 [tool.flet.<PLATFORM>.boot_screen]
name = "flet"

[tool.flet.<PLATFORM>.boot_screen] 下的设置会按每个键覆盖全局的 [tool.flet.boot_screen]。

内置 flet 启动加载屏幕 ​

内置屏幕在以其命名的一个表下进行配置。所有选项都是可选的:

pyproject.toml

toml
[tool.flet.boot_screen.flet]
theme_mode = "auto"                       # auto(默认)、light 或 dark
bgcolor_light = "#ffffff"
bgcolor_dark = "#000000"
spinner_color_light = "blue"
spinner_color_dark = "yellow"
spinner_size = 30                         # 0 或省略 → 不显示转圈
text_color_light = "#000000"
text_color_dark = "#ffffff"
prepare_message = "Preparing your app…"   # 仅 Android;为空/省略 → 不显示消息
startup_message = "Starting up…"          # 为空/省略 → 不显示消息
选项描述
theme_mode使用哪套颜色:auto(跟随设备)、light 或 dark。默认 auto。
bgcolor_light / bgcolor_dark背景颜色。省略时跟随 Flet 默认主题背景。
spinner_color_light / spinner_color_dark转圈颜色。省略时跟随 Flet 默认主题主色。
spinner_size转圈直径,单位为逻辑像素。0 或省略则隐藏转圈。
text_color_light / text_color_dark消息文字颜色。省略时跟随 Flet 默认主题 on-surface 颜色。
prepare_message在 准备中 阶段显示的文本(仅 Android)。为空或省略则不显示消息。
startup_message在 启动中 阶段显示的文本。为空或省略则不显示消息。
fade_out_duration应用就绪时淡出的时长,单位为毫秒。默认 0(立即移除);设为 300 之类的值可淡出。

颜色接受与 Flet 其他地方相同的格式(十六进制如 #ffffff 或命名颜色如 blue)。

自定义启动加载屏幕 ​

要完全控制启动加载屏幕——包括自定义布局与动画——可通过 Flet 扩展提供你自己的 Flutter 控件,并按 name 引用它。实现方式请参阅扩展编写指南中的 Boot screen。

pyproject.toml

toml
[tool.flet.boot_screen]
name = "my_screen"

[tool.flet.boot_screen.my_screen]
# 传给你的控件的任意选项

已废弃

较旧的 [tool.flet.app.boot_screen] 与 [tool.flet.app.startup_screen] 设置(带 show / message)已废弃。它们仍然有效——并会映射到内置的 flet 启动加载屏幕——但你应该迁移到 [tool.flet.boot_screen]。

启动时隐藏应用窗口 ​

平台支持

仅限 Windows、macOS 和 Linux。

Flet 桌面应用(Windows、macOS 或 Linux)可以在窗口隐藏的状态下启动。 这让你的应用能够在向用户展示之前,先完成一些初始化工作(例如添加内容、调整窗口大小或位置)。

请参阅此 代码示例。

解析顺序 ​

其值按以下优先级顺序确定:

  • [tool.flet.<PLATFORM>.app].hide_window_on_start,其中 <PLATFORM> 可以是 windows、macos 或 linux
  • [tool.flet.app].hide_window_on_start
  • FLET_HIDE_WINDOW_ON_START

示例 ​

pyproject.toml

toml
[tool.flet.app]    # 或 [tool.flet.<PLATFORM>.app]
hide_window_on_start = true

深度链接(Deep linking) ​

平台支持

仅限 Android 和 iOS。

深度链接 允许用户通过 URI(统一资源标识符) 直接导航到移动应用内的特定内容。深度链接不会打开应用主页,而是将用户引导到应用内的 特定页面、功能或内容,从而提升用户体验与参与度。

  • Scheme:深度链接 URL 协议,例如 "https" 或 "myapp"。
  • Host:深度链接 URL 主机。

另请参阅:

解析顺序 ​

其值按以下优先级顺序确定:

  1. --deep-linking-scheme 与 --deep-linking-host(仅当两者都提供时)
  2. [tool.flet.<PLATFORM>.deep_linking].scheme / [tool.flet.<PLATFORM>.deep_linking].host,其中 <PLATFORM> 可以是 android 或 ios
  3. [tool.flet.deep_linking].scheme / [tool.flet.deep_linking].host

scheme 与 host 都是必需的;如果缺少任意一个,则不会添加深度链接条目。

示例 ​

bash
flet build <target_platform> \
  --deep-linking-scheme "https" \
  --deep-linking-host "mydomain.com"
toml
[tool.flet.deep_linking]    # 或 [tool.flet.<PLATFORM>.deep_linking]
scheme = "https"
host = "mydomain.com"
模板翻译

在 Android 的 AndroidManifest.xml 中, 上面的 pyproject.toml 示例会被相应地翻译为如下内容:

xml
<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" android:host="mydomain.com" />
</intent-filter>

在 iOS 的 ios/Runner/Info.plist 中, 上面的 pyproject.toml 示例会被相应地翻译为如下内容:

xml
<key>FlutterDeepLinkingEnabled</key>
<true />
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>mydomain.com</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>https</string>
        </array>
    </dict>
</array>

目标架构(Target Architecture) ​

平台支持

仅限 Android 和 macOS。

一个目标平台可能有不同的 CPU 架构,而这些架构又支持不同的指令集。

你可以为特定的 CPU 架构构建应用。这对于减小生成的二进制文件或安装包的体积, 或针对特定设备进行构建很有用。

如需更多/补充信息,请参阅各平台指南: Android、macOS。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --arch
  2. [tool.flet.<PLATFORM>].target_arch,其中 <PLATFORM> 可以是 android 或 macos
  3. [tool.flet].target_arch
  4. 该 <target_platform> 的平台默认值

示例 ​

bash
flet build macos --arch arm64 x86_64
toml
[tool.flet.macos]     # 或 [tool.flet]
target_arch = ["arm64", "x86_64"]

排除文件与目录 ​

可以在构建过程中排除文件和/或目录。这对于减小生成的二进制文件或安装包的体积很有用。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --exclude(可多次使用)
  2. [tool.flet.<PLATFORM>.app].exclude(类型:字符串列表)
  3. [tool.flet.app].exclude(类型:字符串列表)

指定的文件和/或目录应作为相对 应用路径 目录的路径提供。路径按精确匹配 (不支持通配符),并且目录会被递归排除。

build 目录始终被排除。 此外,当目标平台为 web 时,assets 目录始终被排除。

示例 ​

bash
flet build <target_platform> --exclude tests docs
toml
[tool.flet.app]    # 或 [tool.flet.<PLATFORM>.app]
exclude = ["tests", "docs"]

默认排除项 ​

以下内容默认也会被排除,以避免把开发文件打包分发给最终用户:

  • 应用路径下直接的隐藏文件与目录:在所有平台上以 . 开头的名称(例如 .venv、.git、.flet、.idea、.vscode、.env),以及在 Windows 上具有隐藏属性的条目。子目录中的隐藏条目仍会被打包。
  • 任意深度的虚拟环境:通过 python -m venv、uv venv 或 virtualenv 创建的 pyvenv.cfg 文件来识别,无论该目录叫什么名字(例如 venv 或 env)。
  • 任意深度的 __pycache__ 目录。

flet build 会打印出在应用中匹配到的默认排除项。

WARNING

应用路径下的 .env 文件默认不会被打包。如果你的应用在运行时加载它(例如通过 python-dotenv),请用 include 保留它。

如果想把其中某些文件一并打包,可将其列入 include。include 的取值按以下优先级确定:

  1. --include(可多次使用)
  2. [tool.flet.<PLATFORM>.app].include(类型:字符串列表)
  3. [tool.flet.app].include(类型:字符串列表)

include 仅作用于默认排除项,不会覆盖 build、web 上的 assets,也不会覆盖 exclude 中列出的任何内容。

要彻底关闭默认排除,可使用 --no-default-excludes,或在 [tool.flet.app](或 [tool.flet.<PLATFORM>.app])下设置 default_excludes = false。

bash
flet build <target_platform> --include .env
toml
[tool.flet.app]    # 或 [tool.flet.<PLATFORM>.app]
include = [".env"]

编译与清理 ​

Flet 可以在打包过程中将你的应用 .py 文件和/或已安装包的 .py 文件编译为 .pyc 文件(通过 python -m compileall -b)。清理会移除已知的垃圾文件以及你指定的任何额外通配符。

  1. 编译:

    • compile-app:编译应用的 .py 文件
    • compile-packages:编译 site/已安装包的 .py 文件
  2. 清理:

    • cleanup-app:从应用目录移除垃圾文件
    • cleanup-app-files:要从应用目录删除的额外通配符 (隐含 cleanup-app)
    • cleanup-package-files:要从 site-packages 删除的额外通配符 (隐含 cleanup-packages)
    • cleanup-packages:从 site-packages 移除垃圾文件(默认为 true)

默认情况下,Flet 在打包时会编译你的应用和已安装的包到 .pyc。 分发字节码可以避免在每次冷启动时重新编译每个模块——这在移动端是一项显著的启动优化, 因为纯 Python 是从存储的 zip 中导入的,无法将字节码缓存回磁盘。

传入 --no-compile-app / --no-compile-packages(或将 [tool.flet.compile].app / [tool.flet.compile].packages 设为 false)可禁用它——例如为了加快迭代构建, 或为了在打包中保留 .py 源码,从而即使存在语法错误也能完成构建,并且堆栈回溯能显示源码行。

解析顺序 ​

compile-app 与 cleanup-app 的值分别按以下优先级顺序确定:

  1. --compile-app / --cleanup-app
  2. [tool.flet.<PLATFORM>.compile].app / [tool.flet.<PLATFORM>.cleanup].app
  3. [tool.flet.compile].app / [tool.flet.cleanup].app
  4. True / 空列表

compile-packages 与 cleanup-packages 的值分别按以下优先级顺序确定:

  1. --compile-packages / --cleanup-packages
  2. [tool.flet.<PLATFORM>.compile].packages / [tool.flet.<PLATFORM>.cleanup].packages
  3. [tool.flet.compile].packages / [tool.flet.cleanup].packages
  4. True / True

cleanup-app-files 与 cleanup-package-files 的值分别按以下优先级顺序确定:

  1. --cleanup-app-files / --cleanup-package-files
  2. [tool.flet.<PLATFORM>.cleanup].app_files / [tool.flet.<PLATFORM>.cleanup].package_files
  3. [tool.flet.cleanup].app_files / [tool.flet.cleanup].package_files
  4. False / False

示例 ​

bash
flet build <target_platform> \
  --compile-app --compile-packages \
  --cleanup-app-files "**/*.c" "**/*.h" --cleanup-package-files "**/*.pyi"
toml
[tool.flet.compile]     # 或 [tool.flet.<PLATFORM>.compile]
app = true
packages = true

[tool.flet.cleanup]     # 或 [tool.flet.<PLATFORM>.cleanup]
app = true
packages = true
app_files = ["**/*.c", "**/*.h"]
package_files = ["**/*.pyi"]

权限 ​

平台支持

仅限 Android、iOS 和 macOS。

flet build 允许对嵌入到 AndroidManifest.xml、Info.plist 和 .entitlements 文件中的权限、功能与授权进行细粒度控制。

有关设置特定 iOS、 Android 和 macOS 权限,请参阅平台指南。

预定义的跨平台权限包 ​

跨平台权限是命名且预定义的包,会应用某项功能所需的、一组基准的平台特定条目。 每个包都会展开为对应的平台特定等价项。这对于可能不熟悉底层平台 API、或 不愿直接与之打交道的初学者尤其有用。

只有你列出的包会被应用。如果你需要不同的措辞或额外的条目, 请直接设置平台特定的表;这些值会被合并到上层,并可以覆盖包的默认值。 下面的示例展示了每个包对应的确切 pyproject.toml 等价写法。

以下是可用的包列表:

解析顺序 ​

其值按以下优先级顺序确定:

  1. --permissions
  2. [tool.flet].permissions(类型:字符串列表)
  3. []
示例 ​
bash
flet build <target_platform> --permissions location microphone
toml
[tool.flet]
permissions = ["location", "microphone"]

构建模板 ​

flet build 会使用 cookiecutter 模板在 <app_root>/build/flutter 下创建(并复用)一个 Flutter 项目。默认情况下, 该模板会作为 zip 产物从对应的 Flet GitHub Release 下载。所用模板的版本由已安装的 Flet 版本决定。

当模板输入发生变化,或你运行 flet clean 删除 build 目录后, 缓存的项目会被刷新。

模板源 ​

定义要使用的 cookiecutter 构建模板的位置。

支持的值包括:

  • 使用 gh: 前缀的 GitHub 仓库(例如 gh:org/template)
  • 完整的 Git URL(例如 https://github.com/org/template.git)
  • zip URL(例如 https://github.com/flet-dev/flet/releases/download/v0.83.0/flet-build-template.zip)
  • 本地目录路径

解析顺序 ​

其值按以下优先级顺序确定:

  1. --template
  2. [tool.flet.template].url
  3. 与已安装版本匹配的 Flet GitHub Release 的默认 zip URL

示例 ​

bash
flet build apk --template gh:my-org/my-custom-template
toml
[tool.flet.template]
url = "gh:my-org/my-custom-template"

模板引用 ​

定义要从 模板源 检出的分支、标签或提交。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --template-ref
  2. [tool.flet.template].ref
  3. <flet_version>

示例 ​

bash
flet build <target_platform> --template-ref main
toml
[tool.flet.template]
ref = "main"

模板目录 ​

定义 cookiecutter 模板的相对路径。 如果设置了 模板源,该路径被视为其根目录下的子目录; 否则,它相对于模板根目录。

解析顺序 ​

其值按以下优先级顺序确定:

  1. --template-dir
  2. [tool.flet.template].dir
  3. 模板源 的根目录

示例 ​

bash
flet build <target_platform> --template gh:org/template --template-dir sub/directory
toml
[tool.flet.template]
url = "gh:org/template"
dir = "sub/directory"

额外的 flutter build 参数 ​

在 flet build 过程中,flutter build 命令会在内部被调用来为指定平台打包你的应用。 然而,并非所有 flutter build 参数都通过 flet build 命令直接暴露或可用。

关于可能的 flutter build 参数,请参阅 Flutter 文档 指南。对于大多数目标,运行 flutter build <target_platform> --help;对于 ios-simulator,运行 flutter build ios --simulator --help。

重要

传递额外的 flutter build 参数可能导致意外行为。 请自行承担风险,并且仅在你完全清楚自己在做什么时使用!

解析顺序 ​

其值按以下优先级顺序确定:

  1. --flutter-build-args(可多次使用),或 -- 分隔符之后的参数,两者同时给出时合并生效
  2. [tool.flet.<PLATFORM>.flutter].build_args
  3. [tool.flet.flutter].build_args

示例 ​

bash
flet build apk -- \
  --obfuscate \
  --split-debug-info=build/symbols \
  --dart-define=API_URL=https://api.example.com

# 或者,一次传一个参数
flet build apk \
  --flutter-build-args=--obfuscate \
  --flutter-build-args=--split-debug-info=build/symbols \
  --flutter-build-args=--dart-define=API_URL=https://api.example.com
toml
[tool.flet.flutter]     # 或 [tool.flet.<PLATFORM>.flutter]
build_args = [
  "--obfuscate",
  "--split-debug-info=build/symbols",
  "--dart-define=API_URL=https://api.example.com",
]
  • -- 之后的所有内容会原样传给 flutter build。
  • --flutter-build-args 每次只传一个参数。若参数值以 - 开头,请用 = 连接,例如 --flutter-build-args=--obfuscate。
  • flet debug 以同样的方式把它们传给 flutter run。

Flutter 依赖 ​

当你运行 flet build 时,Flet 会生成一个 Flutter 外壳项目,然后使用 pyproject.toml 中的值更新其 pubspec.yaml。

使用:

  • [tool.flet.flutter.pubspec.dependencies] 用于普通的包声明。 (Dart 文档)
  • [tool.flet.flutter.pubspec.dependency_overrides] 用于当你必须强制某个 版本或来源时,例如本地路径或 Git 分支。 (Dart 文档)

值遵循 标准 Pub 依赖语法, 以 TOML 表达。

注意

  • 重要: 在大多数情况下,你通常不需要添加/覆盖 Flutter 依赖。 我们建议你只在完全清楚自己在做什么时才这样做,因为它可能导致意外行为。
  • 如果同一个包同时出现在 pyproject.toml 和最终生成的 pubspec.yaml 中, 以 pyproject.toml 中的值为准。
  • 如果你在 [tool.flet.flutter.pubspec.dependencies] 或 [tool.flet.flutter.pubspec.dependency_overrides] 下使用了 { path = "..." }, 该路径由 Flutter 从生成的 pubspec.yaml 位置解析:<flet_app_directory>/build/flutter/pubspec.yaml。 这意味着相对路径不会从你的 pyproject.toml 文件解析。

示例 ​

pyproject.toml

toml
[tool.flet.flutter.pubspec.dependencies]    # 或 [tool.flet.flutter.pubspec.dependency_overrides]
# 版本号
pkg_1 = "^1.2.3"

# 本地路径
pkg_2 = { path = "../pkg_2" }

# Git(简写形式)
pkg_3 = { git = "https://github.com/org/pkg_3.git" }

# Git(展开形式:URL + ref + 子目录)
pkg_4 = { git = { url = "https://github.com/org/mono_repo.git", ref = "main", path = "packages/pkg_4" } }

# 托管来源
pkg_5 = { hosted = { name = "pkg_5", url = "https://pub.dev" }, version = "^1.0.0" }

# SDK 包(仅用于依赖;通常不用于 dependency_overrides)
flutter_test = { sdk = "flutter" }

详细日志 ​

-v(或 --verbose)与 -vv 标志 会在 flet build 过程中启用所有命令的详细输出。

使用 -v 获取标准/基础详细日志,或使用 -vv 获取更详细的输出(更高的详细级别)。 如果你需要技术支持,我们可能会要求你分享这份详细日志。

控制台输出 ​

在打包后的应用中(flet build 的输出),你的 Python 代码的所有输出,例如 print() 语句、sys.stdout.write() 调用,以及 Python logging 模块的消息, 都会被重定向到一个 console.log 文件。该文件的完整路径可通过 StoragePaths.get_console_log_filename() 或 FLET_APP_CONSOLE 环境变量获取。

注意:FLET_APP_CONSOLE 仅在正式构建中设置; 在开发运行时,输出仍留在你的终端中。

在 Android、iOS 和 macOS 上,同样的输出也会进入平台日志,这通常是在你的开发机上 更容易读取它的方式——参见 Android、 iOS 和 macOS 的"读取应用输出"。本节讲的是如何从应用内部获取它。

日志文件以无缓冲方式写入,让你可以在 Python 程序的任意位置读取它:

python
import os
import flet as ft

async def main(page: ft.Page):
    log_file = await ft.StoragePaths().get_console_log_filename()
    # 或
    # log_file = os.getenv("FLET_APP_CONSOLE")

    with open(log_file, "r") as f:
        logs = f.read()
        page.add(ft.Text(logs)) # 显示在界面上

ft.run(main)

如果你的程序调用 sys.exit(100),完整的日志会自动显示在一个可滚动窗口中。 这是一个用于调试目的的"魔法"退出码:

python
import sys
sys.exit(100)

使用其他任何退出码调用 sys.exit() 都会在不显示日志的情况下终止应用。

持续集成/持续部署(CI/CD) ​

你可以在 CI/CD 流水线中使用 flet build 命令,来自动化 Flet 应用的构建与发布流程。

GitHub Actions ​

你可以使用 GitHub Actions 在每次推送、 拉取请求或手动运行时自动构建你的 Flet 应用。

推荐选项是 官方 Flet 构建 Action, 它封装了 flet build、设置所需工具、在需要时安装 Linux 构建依赖,并 创建一个便于上传的、感知平台的归档。如果你需要对每一步拥有完全控制权, 可以改为在工作流中手动运行 flet build。

Flet build action

yaml
name: Build Flet App [^1]

on: [^2]
  push: [^3]
  pull_request: [^4]
  workflow_dispatch: [^5]

jobs:
  build:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.runner }}
    strategy: [^6]
      fail-fast: false
      matrix:
        include:
          - target: apk
            runner: ubuntu-latest

          - target: aab
            runner: ubuntu-latest

          - target: web
            runner: ubuntu-latest

          - target: linux
            runner: ubuntu-latest

          - target: windows
            runner: windows-latest

          - target: macos
            runner: macos-latest

          - target: ipa
            runner: macos-latest

          - target: ios-simulator
            runner: macos-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6 [^7]

      - name: Build app
        id: build
        uses: flet-dev/flet-build-action@v1 [^8]
        with:
          target: ${{ matrix.target }} [^9]
          runner-python-version: "3.14" [^10]
          bundled-python-version: "3.14" [^11]
          build-number: ${{ github.run_number }} [^12]

      - name: Upload build archive
        uses: actions/upload-artifact@v7 [^13]
        with:
          path: ${{ steps.build.outputs.archive-path }} [^14]
          archive: false [^15]
          if-no-files-found: error [^16]
          overwrite: false
  1. 显示在 Actions 标签页中的工作流显示名。
  2. 自动与手动工作流运行的触发块。
  3. 在每次推送时运行此工作流(除非你限制了分支)。
  4. 在打开/更新拉取请求时运行此工作流。
  5. 允许从 GitHub UI 手动运行(Actions → Run workflow)。
  6. 矩阵策略:每个 include 项都会变成一个并行构建任务。
  7. 检出你的仓库,使此工作流能访问项目文件。文档见此处。
  8. 使用官方 Flet 构建 Action 构建所选目标。文档见此处。
  9. 将当前矩阵目标传给 Action。
  10. GitHub Actions runner 上由 uv 使用的 Python 版本。
  11. 打包进所构建 Flet 应用中的 Python 版本。参见 选择 Python 版本。
  12. 使用 GitHub 运行编号作为应用构建号。参见 Build Number。
  13. 上传由 Flet 构建 Action 创建的归档。文档见此处。
  14. 上传 Action 感知平台的归档输出。
  15. 禁用 upload-artifact 自身的归档包装,因为 Flet 构建 Action 已经创建了归档。
  16. 如果没有找到可上传的归档,工作流会失败,表明构建过程中出了差错。

手动 flet build(Manual flet build)

yaml
name: Build Flet App [^1]

on: [^2]
  push: [^3]
  pull_request: [^4]
  workflow_dispatch: [^5]

env: [^6]
  UV_PYTHON: 3.14 [^7]
  PYTHONUTF8: 1 [^8]

  # https://flet.dev/docs/reference/environment-variables
  FLET_CLI_NO_RICH_OUTPUT: 1 [^9]

jobs:
  build:
    name: Build ${{ matrix.name }}
    runs-on: ${{ matrix.runner }}
    strategy: [^10]
      fail-fast: false
      matrix:
        include:
          # -------- 桌面端 --------
          - name: linux
            runner: ubuntu-latest
            build_cmd: "flet build linux"
            artifact_path: build/linux
            needs_linux_deps: true

          - name: macos
            runner: macos-26
            build_cmd: "flet build macos"
            artifact_path: build/macos
            needs_linux_deps: false

          - name: windows
            runner: windows-latest
            build_cmd: "flet build windows"
            artifact_path: build/windows
            needs_linux_deps: false

          # -------- Android --------
          - name: aab
            runner: ubuntu-latest
            build_cmd: "flet build aab"
            artifact_path: build/aab
            needs_linux_deps: false

          - name: apk
            runner: ubuntu-latest
            build_cmd: "flet build apk"
            artifact_path: build/apk
            needs_linux_deps: false

          # -------- iOS --------
          - name: ipa
            runner: macos-26
            build_cmd: "flet build ipa"
            artifact_path: build/ipa
            needs_linux_deps: false

          - name: ios-simulator
            runner: macos-26
            build_cmd: "flet build ios-simulator"
            artifact_path: build/ios-simulator
            needs_linux_deps: false

          # -------- Web --------
          - name: web
            runner: ubuntu-latest
            build_cmd: "flet build web"
            artifact_path: build/web
            needs_linux_deps: false

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6 [^11]

      - name: Setup uv
        uses: astral-sh/setup-uv@v6 [^12]

      - name: Install Linux dependencies [^13]
        if: matrix.needs_linux_deps [^14]
        shell: bash
        run: |
            sudo apt update --allow-releaseinfo-change
            LINUX_DEPS="$(uv run flet --version --json | jq -r '.linux_dependencies | join(" ")')"
            sudo apt-get install -y --no-install-recommends $LINUX_DEPS
            sudo apt-get clean

      - name: Build app [^15]
        shell: bash
        run: |
          uv run ${{ matrix.build_cmd }} --yes --verbose

      - name: Upload Artifact
        uses: actions/upload-artifact@v7 [^16]
        with:
          name: ${{ matrix.name }}-build-artifact
          path: ${{ matrix.artifact_path }} [^17]
          if-no-files-found: error [^18]
          overwrite: false
  1. 显示在 Actions 标签页中的工作流显示名。
  2. 自动与手动工作流运行的触发块。
  3. 在每次推送时运行此工作流(除非你限制了分支)。
  4. 在打开/更新拉取请求时运行此工作流。
  5. 允许从 GitHub UI 手动运行(Actions → Run workflow)。
  6. 所有任务与步骤共享的环境变量。
  7. uv 使用的 Python 版本。
  8. 强制 Python 输出/IO 使用 UTF-8 模式。在 Windows 构建上尤其有用。
  9. 禁用 flet build 的富文本输出,以便 CI 日志更易读。
  10. 矩阵策略:每个 include 项都会变成一个并行构建任务。
  11. 检出你的仓库,使此工作流能访问项目文件。文档见此处。
  12. 在 runner 上安装 uv。文档见此处。
  13. 安装 Linux 桌面端构建所需的 Linux 系统包。
  14. 仅为需要它的矩阵项运行 Linux 包安装。
  15. 每个目标的主构建步骤。执行由 matrix.build_cmd 定义的目标专属命令。
  16. 将构建输出文件作为可下载的构件上传。文档见此处。
  17. 每个构建目标期望的构件路径。
  18. 如果没有找到可上传的文件,工作流会失败,表明构建过程中出了差错。

两种工作流变体都会针对所有主要目标进行构建,并将每次构建输出作为构件上传。 你可以根据具体需求进一步自定义工作流,例如限制构建目标,或添加签名、公证、 应用商店上传或部署步骤。

故障排查 ​

预发布版本兼容性 ​

如果你使用 Flet Python 包 的预发布版本(例如 0.80.6.devNNNN)来构建应用, 构建模板 可能仍会解析最新的稳定版 flet Flutter 包, 这可能导致版本不兼容问题。

为什么?:正常情况下,Flet Python 包的每次预发布都需要 一个匹配的 Flutter Flet 包预发布版本,以保证兼容性。 然而,我们不会向 pub.dev 发布 Flutter 包的预发布版本。 因此,构建模板会改为解析最新的稳定版 Flutter flet 发布。

这为用 flet build 打包的应用带来了版本不匹配/不兼容:

  • 你的 Python 代码可能依赖新引入的控件或功能。
  • 打包后的 Flutter 外壳可能仍在使用较旧的稳定 flet 版本。
  • 在运行时,应用会失败,因为 Flutter 层无法识别你预发布 flet 包中的新控件/功能, 导致类似 Unknown control: <ControlName> 的错误。

注意:此问题不影响开发工作流(例如使用 flet run 运行应用), 因为 flet Flutter 依赖只在 flet build 过程中解析。

解决方案 ​

经验法则是,如果你使用预发布版的 Flet Python 包,在构建应用之前,务必确保 Flutter flet 依赖与同一个开发版本对齐:

[^1]: 将 Flutter flet 依赖覆盖为指向对应的开发版 Git 引用。

pyproject.toml

```toml
[tool.flet.flutter.pubspec.dependency_overrides]
flet = { git = { url = "https://github.com/flet-dev/flet.git", ref = "main", path = "packages/flet" } }
```

[^2]: 清除构建缓存后重新构建应用(运行 flet clean 删除 build 目录)

为了确保可复现的构建(例如在生成环境或 CI 中),建议使用特定的提交 SHA,而不是分支或标签引用。


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