Skip to content

用 flet pack 把 Flet 应用打包成独立的桌面可执行文件——这是一个轻量的、基于 PyInstaller 的方案,可作为 flet build 的替代。用户运行打包后的应用,无需安装 Python 解释器或任何模块。

它与 flet build 的关系 ​

这两个命令都受支持——它们分别处在「速度 vs 控制」曲线的不同位置:

flet packflet build
目标平台仅桌面端:Windows、macOS、Linux桌面端、移动端(Android/iOS),以及 web
工具链PyInstallerFlutter SDK(自动安装)
应用运行方式你的 Python 代码与预构建的 Flet 桌面客户端一起运行Flutter 编译的应用,内嵌 Python,进程内运行
Python 依赖由 PyInstaller 对你的导入做静态分析来发现按你声明的 应用依赖 完整安装
构建时间快——没有原生编译较慢——一次完整的 Flutter 构建
可定制程度图标以及可执行文件/打包的元数据一切:图标、启动画面、构建模板、签名与商店打包

想要快速产出桌面产物时,用 flet pack;面向移动端或 web,或者需要更深度的定制时,用 flet build。

与 PyInstaller 本身一样,flet pack 不是交叉编译器:针对每个目标操作系统分别运行——CI 能让这件事变得毫不费力。

前置条件 ​

PyInstaller 负责打包,必须先安装:

bash
pip install pyinstaller

打包 ​

在包含你程序的目录下运行:

bash
flet pack your_program.py

打包后的应用落在 dist 文件夹中 (--distpath 可改变它):在 Windows 和 Linux 上是单文件可执行文件, 在 macOS 上是一个 .app 打包。传入 --onedir 可改为生成单文件夹打包,而非单个文件(macOS 始终生成 .app 打包)。试着运行一下:

bash
open dist/your_program.app
bash
dist\your_program.exe
bash
dist/your_program

默认情况下,可执行文件或打包以 Python 脚本的名字命名;用 --name 修改:

bash
flet pack your_program.py --name bundle_name

如果上次运行残留了非空的 build 或 dist 文件夹,flet pack 会在删除前询问——传入 --yes 可跳过所有提示 (在 CI 中很有用)。

要分发,就把 dist 文件夹的内容压缩成 zip 交给用户——他们运行它不需要安装 Python 或 Flet。

自定义图标 ​

用 --icon 设置图标:

bash
flet pack your_program.py --icon your-icon.ico

请提供目标平台原生格式的图标:Windows 用 .ico,macOS 用 .icns。它会同时应用到外层可执行文件和内嵌的 Flet 查看器,这样应用窗口、Dock/任务栏条目以及可执行文件本身都保持一致。

::: infoLinux 的处理方式不同 Linux 没法把图标放进可执行文件内部——桌面环境从已安装的桌面条目中读取它。传入一个 .png,flet pack 会替你把 条目和图标都写好供你安装;参见 Linux 任务栏身份。 :::

Linux 任务栏身份 ​

flet pack 启动的是那个共享的、预构建的 Flet 客户端,所以如果没有额外帮助,每个打包后的应用都会以该二进制文件的名字出现在任务栏上——被归到一组,并标注为 flet。为避免这种情况,应用会以自身的身份重新启动 (参见 FLET_APP_ID):当你传入时采用 --bundle-id,否则采用可执行文件的名字。

--bundle-id 也能让你主动选择这个身份,而不是从可执行文件的名字继承——如果可执行文件名叫某个不该作为桌面条目键名的东西,这么做是值得的——比如带版本号的 my-app-1.2.3。

这就让应用拥有了属于自己的任务栏分组和标签。它的显示名称和图标来自别处:一个桌面条目,桌面环境通过 StartupWMClass 把它与窗口匹配起来。flet pack 会在可执行文件旁边写一个条目——如果你给 --icon 传了 .png,还会一并写入图标:

dist/
  my-app                    the executable
  com.example.my_app.desktop
  com.example.my_app.png    only when --icon is a .png

Name= 来自 --product-name (回退到可执行文件的名字),Comment= 来自 --file-description。不会替你安装任何东西,因为安装会作为构建的副作用改动你的应用菜单。你自己把这两个文件复制到合适位置并刷新缓存:

bash
cp dist/com.example.my_app.desktop ~/.local/share/applications/
update-desktop-database ~/.local/share/applications

# 仅当你给 --icon 传了 .png 时才需要
mkdir -p ~/.local/share/icons/hicolor/256x256/apps
cp dist/com.example.my_app.png ~/.local/share/icons/hicolor/256x256/apps/
gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor

移动可执行文件会破坏 Exec=

条目指向 flet pack 构建二进制文件的位置,因为那是写入它时唯一已知的位置。如果你把可执行文件安装到了别处——/opt、~/.local/bin——请编辑 Exec= 使之匹配:

bash
sed -i 's|^Exec=.*|Exec="/opt/my-app/my-app"|' ~/.local/share/applications/com.example.my_app.desktop

或者交给 flet build 打包

flet build linux 会为每个应用编译一个独立的运行器,所以身份是内置的,而不是在启动时套用。如果你想让打包工作被自动处理,而不是自己拼装,就用它。

包含静态资源 ​

如果你的应用使用了静态资源,用 --add-data 包含它们,格式为 source:destination:

bash
flet pack your_program.py --add-data "assets:assets"

这个选项可以重复传入,以包含多个文件或文件夹。

可执行文件与打包元数据 ​

操作系统展示的关于你应用的一些细节可以定制。

在 macOS 上——打包的「关于」对话框以及 Dock/活动监视器条目:

Flet 应用打包的关于信息

在 Windows 上——可执行文件的「详细信息」属性对话框:

和图标一样,元数据会同时嵌入外层可执行文件和其中内嵌的 Flet 查看器。

更多选项 ​

  • --hidden-import — 添加被动态导入、因而被 PyInstaller 静态分析遗漏的模块。
  • --add-binary — 打包额外的二进制文件。
  • --debug-console 1 — 保留一个显示 Python 输出的控制台窗口, 用于排查打包后应用的问题。
  • --uac-admin — 启动时请求提升的权限(Windows)。
  • --codesign-identity — 签名应用打包(macOS)。
  • --pyinstaller-build-args — 把任何其他参数直接透传给 底层的 pyinstaller 命令,每次只传一个。若参数值以 - 开头,请用 = 连接, 例如 --pyinstaller-build-args=--clean。
  • -- — 把其后的所有内容直接透传给 pyinstaller,例如 flet pack main.py -- --clean --log-level=WARN。

完整选项列表见 flet pack 参考。

在 CI 中打包 ​

由于每个操作系统必须各自打包自己的产物,用 CI 矩阵可以一次性产出全部三个:

yaml
name: Pack Flet App

on:
  push:
  workflow_dispatch:

jobs:
  pack:
    name: Pack on ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [windows-latest, macos-latest, ubuntu-latest]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Setup Python
        uses: actions/setup-python@v6
        with:
          python-version: "3.14"

      - name: Install dependencies
        run: pip install flet pyinstaller [^1]

      - name: Pack app
        run: flet pack your_program.py --yes [^2]

      - name: Upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: your_program-${{ matrix.os }}
          path: dist
  1. 也在这里安装你应用自身的依赖——例如 pip install -r requirements.txt。
  2. --yes 跳过关于删除先前 build 和 dist 文件夹的交互提示。

故障排查 ​

症状原因与修复
仅在打包后的应用内出现 ModuleNotFoundError该模块是动态导入的,所以 PyInstaller 的静态分析漏掉了它——用 --hidden-import <module> 重新打包。
打包后的应用退出或行为异常,且没有可见错误用 --debug-console 1 重新打包,以打开一个显示 Python 输出和回溯信息的控制台窗口。
macOS:在其他 Mac 上出现 "App" is damaged and can't be opened下载的应用必须经过签名与公证,Gatekeeper 才会运行。用 --codesign-identity 签名打包,然后公证并装订——Notarization 一节解释了相关概念与命令,适用于任何已签名的应用。flet build macos 会自动完成整条链路。

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