跳到主要内容

打包应用以进行分发

简介

Flet CLI提供了flet build命令,允许将Flet应用打包为独立的可执行文件或安装包进行分发。

flet build命令取代了flet pack(将应用打包为桌面应用程序)和flet publish(将应用打包为静态网站)命令,并允许将您的Flet应用程序转换为Android或iOS捆绑包、桌面应用程序和静态网站。

对于构建桌面应用程序,flet build不再依赖于flet pack中使用的PyInstaller,而是使用Flutter SDK生成快速、离线、完全可定制(具有自定义的图标、关于对话框和元数据)的可执行文件,其中Python运行时嵌入到可执行文件中并在进程中运行。

flet publish相比,使用flet build构建的静态网站具有更快的加载时间,因为所有Python依赖现在被打包到一个单独的归档文件中,而不是在运行时使用micropip拉取。flet build web还会检测Pyodide中内置的原生Python ,如bcrypthtml5libnumpy等等,并从Pyodide包注册表中安装它们。

先决条件

Flutter SDK

必须安装Flutter SDK 3.16或更高版本,并将flutterdart命令的路径添加到PATH环境变量中。

在macOS上,我们建议使用"下载和安装"的方法安装Flutter SDK。

在Linux上,我们建议使用第二种方法:手动安装安装Flutter SDK(不要使用snap安装Flutter)。

请注意Flutter对每个平台的要求,例如macOS上的XCode和Cocopods、Windows上的Visual Studio 2022,或Linux上的其他工具和库。

Linux要求

GStreamer

在Linux上构建Flet应用程序需要安装GStreamer库。

要在Ubuntu/Debian上安装最小的GStreamer库集,请运行以下命令:

apt install libgtk-3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev

要安装完整的GStreamer库集:

apt install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

有关在其他Linux发行版上安装的详细说明,请参见此指南

Windows要求

启用开发人员模式

在Windows上运行flet build时,您可能会遇到以下错误:

Building with plugins requires symlink support.

Please enable Developer Mode in your system settings. Run
start ms-settings:developers
to open settings.

请根据此Stack Overflow回答中的说明启用Windows 11中的开发人员模式。

构建平台矩阵

以下矩阵显示您应该在哪个操作系统上运行flet build命令,以便为特定平台构建软件包:

构建平台 / 目标平台ipaapk/aabmacoslinuxwindowsweb
macOS
Windows✅ (WSL)
Linux

项目结构

flet build 命令假设以下的 Flet 项目结构。

/assets/
icon.png
main.py
requirements.txt
pyproject.toml

main.py 是你的 Flet 应用的入口点,在末尾使用 ft.app(main)。可以使用 --module-name 参数指定不同的入口点。

assets 是一个可选的目录,包含应用程序的资源(图像、声音、文本和其他应用所需的文件),以及用于应用程序图标和启动画面的图像。

如果只提供了 icon.png(或其他支持的格式,如 .bmp.jpg.webp),它将被用作生成所有平台的图标和启动画面的源图像。有关图标和启动画面的更多信息,请参阅下面的部分。

requirements.txt 是一个标准的 pip 文件,包含你的 Flet 应用所需的 Python 依赖项列表。如果没有提供此文件,则只会安装 flet 依赖项。

不要使用 pip freeze

不要使用 pip freeze > requirements.txt 命令为将在移动设备上运行的应用程序创建requirements.txt。当你在桌面上运行 pip freeze 命令时,requirements.txt 将包含不适用于移动设备的依赖项,如 watchdog

requirements.txt 中手动选择仅包含你的应用程序所需的直接依赖项,以及 flet

pyproject.toml 也可以被 flet build 命令用来获取项目依赖项列表。然而,如果同时存在 requirements.txtpyproject.toml,则会忽略 pyproject.toml

以该结构开始的最简单的方法是使用 flet create 命令:

flet create myapp

其中 myapp 是目标目录。

pyproject.toml

尚不支持从 pyproject.toml 中读取依赖项(问题),请改用 requirements.txt

工作原理

flet build <target_platform> 命令可以从 Flet 应用目录的根目录运行:

<flet_app_directory> % flet build <target_platform>

其中 <target_platform> 可以是以下之一:apkaabipawebmacoswindowslinux

当从不同的目录运行时,可以提供 Flet 应用程序的目录路径:

flet build <target_platform> <path_to_python_app>

构建结果被复制到 <python_app_directory>/build/<target_platform>。可以使用 --output 选项指定自定义输出目录:

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

flet build 使用 Flutter SDK 和 Flutter 包的数量来从 Flet 应用程序构建分发包。

当你运行 flet build <target_platform> 命令时,它会:

  • https://github.com/flet-dev/flet-build-template 模板在临时目录中创建一个新的 Flutter 项目。Flutter 应用将包含打包的 Python 应用,并使用 fletserious_python 包来运行 Python 应用程序和渲染其用户界面。项目是临时的,并在完成后被删除。
  • assets 目录中复制自定义图标和启动画面图像到 Flutter 项目中。
  • 使用 flutter_launcher_icons 包为所有平台生成图标。
  • 使用 flutter_native_splash 包为 web、iOS 和 Android 目标生成启动画面。
  • 使用 serious_python 包的 package 命令打包 Python 应用。当前目录和子目录中的所有 Python 文件都将编译为 .pyc 文件。除了 build 目录之外的所有文件都将被添加到包含资产的包中。
  • 运行 flutter build <target_platform> 命令以生成可执行文件或安装包。
  • 将构建结果复制到 build/<target_platform> 目录。

日志记录

所有的 Flet 应用程序的输出都会被重定向到 stdoutstderr(例如所有的 print() 语句或 sys.stdout.write() 调用,Python logging 库),并存储在 out.log 文件中。这个文件是无缓冲写入的,所以你可以在你的 Python 程序中的任何时刻通过简单的方式检索到日志:

with open("out.log", "r") as f:
log = f.read()

AlertDialog 或其他控件可以用来显示 log 变量的值。

当调用 sys.exit() 并且设置退出码为 100(魔法代码)时,整个日志将会显示在可滚动的窗口中。

import sys
sys.exit(100)

当使用其他的退出码调用 sys.exit() 时,将会直接终止(关闭)应用程序,并不会显示日志。

flet build web

将 Flet Python 应用程序发布为在浏览器中完全运行的静态网站(SPA),无需在服务器端运行任何代码。

Pyodide 是 CPython 在 WebAssembly(WASM)上的移植,它是一项新兴技术,具有一些限制。 Pyodide 自带了一大堆内置包。然而,要使用来自 PyPI 的 Python 包,它必须是一个纯 Python 包或者提供为 Emscripten 构建的二进制文件的 wheel 包

静态网站 vs 服务器端

Flet 静态网站的优点:

  • 用户生成事件(点击、文本字段更改、拖动)与页面更新之间没有延迟。没有 web 服务器调用,也没有 WebSocket——Python 程序直接通过 JavaScript 与 Flutter UI 进行通信。
  • 低成本托管——Flet 静态应用程序不需要在服务器上运行任何代码,因此可以在任何地方托管:GitHub Pages、Cloudflare Pages、Replit、Vercel、共享托管或自己的 VPS。
  • 更高可扩展性——Flet 静态应用程序完全在浏览器中运行,如果它不使用任何服务器端 API,那么可以通过 CDN 扩展到任意数量的用户。

Flet 静态网站的缺点:

  • 加载时间较慢——它需要额外的时间来下载和初始化 Python 引擎(Pyodide)以及下载包含 Flet 应用程序的包。
  • Python 兼容性有限——并非每个在本机 Python 中工作的程序都可以在 Pyodide 中运行。
  • 性能较低——Pyodide 目前比原生 Python 慢 3 倍至 5 倍,因此具有大量处理的 Flet 应用程序最好部署为服务器端。

异步或同步

无论是异步的还是非异步的 Flet 应用程序都可以发布为静态网站。在并发性方面,该网站只有一个线程和一个用户——你。如果你的应用程序具有 CPU 密集型逻辑,它可能会影响 UI 的响应能力,无论应用程序是否是异步的。

但是,如果你的应用程序包含 I/O 逻辑(例如用于 Pyodide 的 fetch 包装器),这在浏览器中是异步的定义,那么你的应用程序必须是异步的。

你可以使用 Python 的内置 http.server 模块 来测试发布的 Web 应用程序:

构建网站

要将 Flet 应用程序发布为静态网站,请在 Flet 应用程序的根目录中运行以下命令:

flet build web

静态网站将发布到 ./build/web 目录中。

测试网站

你可以使用 Python 的内置 http.server 模块 来测试发布的 Flet 应用程序:

python -m http.server --directory build/web

在浏览器中打开 http://localhost:8000 来检查已发布的应用程序。

打包资源

一旦网站发布,assets 目录中的所有文件都会被“原样”复制到网站的根目录。

这允许用你自己的内容覆盖诸如 favicon.pngmanifest.json 等内容。

URL 策略

Flet应用程序支持两种配置基于URL的路由的方式:

  • 路径(默认)-路径以没有哈希的方式读取和写入。例如,fletapp.dev/path/to/view
  • 哈希-路径以哈希片段的形式读取和写入。例如,fletapp.dev/#/path/to/view

如果托管提供商支持单页应用(SPA)渲染,您可以保持默认的“路径”URL策略,因为它提供了漂亮的URL。

但是,如果托管提供程序(如GitHub Pages)不支持SPA模式,则需要使用“哈希”URL策略发布应用程序。

使用--route-url-strategy参数更改URL策略。

Web渲染器

您可以使用--web-renderer选项将默认的“canvaskit”网页渲染器(更多关于渲染器的信息)更改为“html”:

flet build web --web-renderer html

彩色表情符号

为了减小应用程序的大小,默认的“CanvasKit”渲染器不使用彩色表情符号,因为带有彩色表情符号的字体文件约为8 MB。

但是,您可以使用--use-color-emoji标志选择使用彩色表情符号:

flet build web --use-color-emoji

或者,切换到使用浏览器字体的html渲染器。

在子目录中托管网站

多个Flet应用程序可以托管在单个域中-每个应用程序在自己的子目录中。

要使发布的Flet应用程序在子目录中工作,您必须使用--base-url选项发布它:

flet build web --base-url <sub-directory>

例如,如果应用程序的URL是https://mywebsite.com/myapp,则必须使用--base-url myapp发布。

启动画面

默认情况下,生成的Web应用程序将显示一个启动画面,其中包含来自assets目录(见下文)或Flet标志的图像。您可以使用--no-web-splash选项禁用Web应用程序的启动画面。

flet build apk

从您的应用程序构建一个Android APK文件。

此命令构建发布版本。“发布”构建不支持调试,适用于部署到应用商店。如果您要将应用程序部署到Play商店,推荐使用Android App Bundles(AAB)或分割APK以减小APK大小。

启动画面

默认情况下,生成的Android应用程序将显示一个启动画面,其中包含来自assets目录(见下文)或Flet标志的图像。您可以使用--no-android-splash选项禁用Android应用程序的启动画面。

将APK安装到设备

将APK安装到设备的最简单方法是使用adb(Android调试桥)工具。

adb是Android SDK的一部分。例如,在macOS上,如果使用Android Studio安装了Android SDK, adb工具的位置将位于~/Library/Android/sdk/platform-tools/adb处。

查看此文章获取有关在各个平台上安装和使用adb工具的详细信息。

要将APK安装到设备,请运行以下命令:

adb install <path-to-your.apk>

如果您的计算机连接了多个设备(例如模拟器和物理手机),可以使用-s选项指定要将.apk安装在哪个设备上:

adb -s <device> install <path-to-your.apk>

其中 <device> 可以通过 adb devices 命令找到。

flet build aab

从您的应用程序构建一个Android App Bundle(AAB)文件。

此命令构建发布版本。“发布”构建不支持调试,适用于部署到应用商店。App bundle是发布到Play商店的推荐方式,因为它可以改善您的应用程序大小。

启动画面

默认情况下,生成的Android应用程序将显示一个带有来自assets目录(见下文)或Flet徽标的图像的启动画面。您可以使用--no-android-splash选项禁用Android应用程序的启动画面。

flet build ipa

构建用于分发的iOS存档包和IPA文件(仅适用于MacOS主机)。

功能尚未完成

适用于在设备上运行或发布到AppStore的iOS软件包的创建通常是一个复杂的过程,涉及许多方面。如果它对您的特定情况起作用或者不起作用,并且需要对Flutter项目模板进行一些更改,请告诉我们。

要成功生成IPA,您需要为以下参数提供正确的值:

  • --org - 以反向域名表示法表示的组织名称,例如com.mycompany(默认值为com.flet)。该值与--project结合使用,作为iOS和Android bundle ID使用。
  • --project - 以C风格标识符格式(小写字母数字和下划线)表示的项目名称,用于构建bundle ID和作为bundle可执行文件的名称。默认情况下,它是Flet应用程序目录的名称。
  • --team - 团队ID,用于查找配置文件。如果没有提供团队ID,将生成一个未签名的iOS存档。

启动画面

默认情况下,生成的iOS应用程序将显示一个带有来自assets目录(见下文)或Flet徽标的图像的启动画面。您可以使用--no-ios-splash选项禁用iOS应用程序的启动画面。

flet build macos

构建MacOS桌面应用程序。

flet build linux

构建Linux桌面应用程序。

flet build windows

构建Windows桌面应用程序。

图标

您可以使用Flet应用程序的assets目录中的图像自定义所有平台(不包括Linux)的应用程序图标。

如果只提供icon.png(或其他支持的格式,如.bmp.jpg.webp),它将被用作生成所有图标的源图像。

  • iOS - icon_ios.png(或任何支持的图像格式)。推荐的最小图像尺寸为1024 px。图像不应该是透明的(具有alpha通道)。默认值为自动删除alpha通道的icon.png
  • Android - icon_android.png(或任何支持的图像格式)。推荐的最小图像尺寸为192 px。默认为icon.png
  • Web - icon_web.png(或任何支持的图像格式)。推荐的最小图像尺寸为512 px。默认为icon.png
  • Windows - icon_windows.png(或任何支持的图像格式)。将生成256 px大小的ICO。默认为icon.png。如果提供了icon_windows.ico文件,它将被直接复制到windows/runner/resources/app_icon.ico中,不做修改。
  • macOS - icon_macos.png(或任何支持的图像格式)。推荐的最小图像尺寸为1024 px。默认为icon.png

启动画面

您可以使用Flet应用程序的assets目录中的图像自定义iOS、Android和Web应用程序的启动画面。

如果只提供splash.pngicon.png(或其他支持的格式,如.bmp.jpg.webp),它将被用作生成所有启动画面的源图像。

  • iOS(明亮模式) - splash_ios.png(或任何支持的图像格式)。默认为splash.png,然后是icon.png
  • iOS(暗黑模式) - splash_dark_ios.png(或任何支持的图像格式)。默认为明亮的iOS启动画面,然后是splash_dark.png,然后是splash.png,然后是icon.png
  • Android(明亮模式) - splash_android.png(或任何支持的图像格式)。默认为splash.png,然后是icon.png
  • Android(暗黑模式) - splash_dark_android.png(或任何支持的图像格式)。默认为明亮的Android启动画面,然后是splash_dark.png,然后是splash.png,然后是icon.png
  • Web(明亮模式) - splash_web.png(或任何支持的图像格式)。默认为splash.png,然后是icon.png
  • Web(暗黑模式) - splash_dark_web.png(或任何支持的图像格式)。默认为明亮的Web启动画面,然后是splash_dark.png,然后是splash.png,然后是icon.png--splash-color选项指定亮色模式下启动画面的背景颜色,默认为#ffffff

--splash-dark-color选项指定暗色模式下启动画面的背景颜色,默认为#333333

Flet 应用的入口点

默认情况下,flet build命令将main.py作为您的 Flet 应用的入口点,即文件末尾带有ft.app(main)的文件。您可以使用--module-name参数指定不同的入口点。

版本控制

您可以使用--build-number--build-version参数为构建的可执行文件或软件包提供版本信息。这些信息用于区分应用商店和Google Play中的不同构建/发布,并在关于对话框中显示给用户。

--build-number - 整数(默认为1),用作内部版本号的标识符。每个构建必须具有唯一的标识符,以区分它与先前构建。它用于确定一个构建是否比另一个构建更新,较高的数字表示更新时间较近的构建。

--build-version - “x.y.z”字符串(默认为1.0.0),用作显示给用户的版本号。对于您应用的每个新版本,您都需要提供一个版本号来区分它与先前的版本。

自定义打包模板

为了创建临时的 Flutter 项目,flet build使用存储在https://github.com/flet-dev/flet-build-template仓库中的[cookiecutter](https://cookiecutter.readthedocs.io/en/stable/)模板。

您可以自定义该模板以适应特定需求,然后使用flet build时使用它。

--template选项可用于提供仓库的URL或包含自定义模板的目录的路径。对于 GitHub 仓库,使用gh:前缀,例如gh:{my-org}/{my-repo};或者提供完整的 Git 仓库路径,例如https://github.com/{my-org}/{my-repo}.git

对于 Git 仓库,您可以使用--template-ref选项来检出特定的分支/标签/提交。

--template-dir选项指定相对于--template选项给出的仓库中的 cookiecutter 模板的路径。当未使用--template选项时,该选项指定相对于<user-directory>/.cookiecutters/flet-build-template的路径。

flutter build命令的额外参数

--flutter-build-args选项允许在构建过程中传递额外的参数给flutter build命令。该选项可以多次使用。

例如,如果您想添加--no-tree-shake-icons选项:

flet build macos --flutter-build-args=--no-tree-shake-icons

要传递一个具有值的选项:

flet build ipa --flutter-build-args=--export-method --flutter-build-args=development

本地 Python 软件包

本地 Python 软件包(与仅使用 Python 编写的“纯” Python 软件包相对)是部分使用 C、Rust 或其他语言编写生成本机代码的软件包。例如,numpycryptographylxmlpydantic

当使用flet build命令为 iOS 和 Android 打包 Flet 应用时,这些软件包无法从 PyPI 安装,因为 Android 和 iOS 平台没有相关的轮子(.whl)。

因此,在运行flet build命令之前,您需要在计算机上为 Android 和/或 iOS 编译本机软件包。

正在进行的工作

我们正在积极开发自动化下面描述的过程 - 这是我们的工作流程中的第一个项目。

Android

Flet 使用 Kivy for Android 构建 Android 上的 Python 和本地 Python 软件包。

要使用自定义本机软件包构建自己的 Python 发行版本,并在flet build命令中使用它,您需要使用 Kivy for Android 提供的p4a工具。

p4a命令行工具可以在 macOS 和 Linux(Windows 上的 WSL)上运行。

要获取 Android SDK,请安装 Android Studio。

在 macOS 上,Android SDK 位于$HOME/Library/Android/sdk

安装 Temurin8 以获得sdkmanager工具所需的 JRE 1.8:

brew install --cask temurin8
export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home

设置以下环境变量:

export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk"
export NDK_VERSION=25.2.9519653
export SDK_VERSION=android-33

sdkmanager的路径添加到PATH中:

export PATH=$ANDROID_SDK_ROOT/tools/bin:$PATH

通过https://developer.android.com/ndk/downloads/或Android SDK Manager安装Android SDK和NDK:

echo "y" | sdkmanager --install "ndk;$NDK_VERSION" --channel=3
echo "y" | sdkmanager --install "platforms;$SDK_VERSION"

创建新的Python虚拟环境:

python3 -m venv .venv
source .venv/bin/activate

从Flet的分支中安装p4a - 它固定了与flet build生成的代码兼容的Python 3.11.6版本:

pip3 install git+https://github.com/flet-dev/python-for-android.git@3.11.6

安装cython

pip install --upgrade cython

运行p4a命令,使用逗号分隔的自定义Python库,比如以下示例中的numpy

p4a create --requirements numpy --arch arm64-v8a --arch armeabi-v7a --arch x86_64 --sdk-dir $ANDROID_SDK_ROOT --ndk-dir $ANDROID_SDK_ROOT/ndk/$NDK_VERSION --dist-name mydist

在"是否要自动安装JDK前提?[y/N]"中选择No。

注意: 使用p4a命令构建的库应该在this folder中有一个recipe。您可以在此处提交请求以创建所需库的recipe,或您也可以自己创建一个recipe并提交PR。

p4a命令完成后,Python分发包含您的自定义库将位于:

$HOME/.python-for-android/dists/mydist

在运行flet build apk命令构建您的Flet Android应用程序的终端中,运行以下命令将分发的完整路径存储在SERIOUS_PYTHON_P4A_DIST环境变量中:

export SERIOUS_PYTHON_P4A_DIST=$HOME/.python-for-android/dists/mydist

通过运行flet build apk命令构建.apk文件。

您的应用程序包现在包含自定义Python库。

iOS

Flet使用Kivy for iOS来构建iOS的Python和本地Python包。

要使用带有自定义本地包的自定义Python分发,以及在flet build命令中使用它,您需要使用Kivy for iOS提供的toolchain工具。

toolchain命令行工具只能在macOS上运行。

首先创建一个新的Python虚拟环境,并按照这里中的说明从Flet的分支安装kivy-ios包:

pip install git+https://github.com/flet-dev/python-for-ios.git

使用您需要构建的包的列表运行toolchain命令,例如构建numpy

toolchain build numpy

注意: 使用toolchain命令构建的库应该在this folder中有一个recipe。您可以在此处提交请求以创建所需库的recipe,或您也可以自己创建一个recipe并提交PR。

您还可以使用pip安装不需要编译的包:

toolchain pip install flask

在这种情况下,您不需要将该包包含在Flet应用程序的requirements.txt中。

toolchain命令完成后,您应该在dist目录中找到所需的一切。

通过运行realpath dist命令获取dist目录的完整路径。

在运行flet build ipa命令构建您的Flet iOS应用程序的终端中,运行以下命令将dist的完整路径存储在SERIOUS_PYTHON_IOS_DIST环境变量中:

export SERIOUS_PYTHON_IOS_DIST="<dist目录的完整路径>"

通过运行 flet build ipa 命令来构建您的应用程序。

您的应用程序包现在包括自定义的Python库。

详细日志

使用 --verbose-vv 选项可以在 flet build 运行期间查看所有命令的输出。 如果您需要支持,我们可能会要求您提供详细的日志。