跳到主要内容

Flet FastAPI 和异步 API 改进

· 阅读需 9 分钟

Flet 使编写动态的实时 Web 应用程序变得非常有趣!

Flet 0.21.0 进一步改进了 Web 应用程序开发体验以及在 Flet 应用中使用 asyncio API 的体验。

以下是Flet 0.21.0的新功能:

用Uvicorn的FastAPI取代内置Web服务器

从Flet诞生之初开始,用于服务Web应用的内置Web服务器是用Go编写的,名为“Fletd”。当你运行flet run --web命令时,它会在后台启动。Fletd是Flet Python轮子的一部分,增加了几兆字节的大小。此外,Python应用使用WebSockets与Fletd Web服务器通信,有时会增加明显的开销。

Flet 0.10.0中,我们添加了对FastAPI的支持,以使用AsyncIO API构建“严肃的”Web应用。

现在,在Flet 0.21.0中,内置Web服务器已被完全移除,取而代之的是FastAPI和Uvicorn。Fletd不再是Flet分发版的一部分。

使用FastAPI意味着不再有通信开销,因为Web服务器是Flet应用的一部分。此外,你不需要做任何额外的步骤即可使用FastAPI在生产环境中托管你的应用——只需使用相同的ft.app(main)命令运行你的应用。

重大变更

flet_fastapi包已被弃用,其内容已移至flet包中的flet.fastapi模块。如果你在Flet应用中使用了FastAPI,请将:

import flet_fastapi

替换为:

import flet.fastapi as flet_fastapi

使用任何 ASGI Web 服务器进行托管

你可以使用任何兼容 ASGI 的服务器托管你的 Flet Web 应用程序,如 Uvicorn(默认使用),HypercornDaphne

只需告诉 Flet 导出 ASGI 应用程序:

main.py
import flet as ft

def main(page: ft.Page):
page.add(ft.Text("Hello ASGI!"))

app = ft.app(main, export_asgi_app=True)

然后用 Hypercorn 运行:

hypercorn main:app --bind 0.0.0.0:8000

Web应用环境变量

Web 应用程序托管的每个方面都可以通过环境变量控制:

  • FLET_FORCE_WEB_SERVER - 设置为 true 强制运行应用程序作为 Web 应用程序。在无头 Linux 主机上自动设置。
  • FLET_SERVER_PORT - 运行应用程序的 TCP 端口。如果程序在 Linux 服务器上运行或设置了 FLET_FORCE_WEB_SERVER,则为 8000;否则为随机端口。
  • FLET_SERVER_IP - 监听 Web 应用程序的 IP 地址,例如 127.0.0.1。默认是 0.0.0.0 - 绑定到所有服务器 IP。
  • FLET_ASSETS_DIR - 应用程序 "assets" 目录的绝对路径。
  • FLET_UPLOAD_DIR - 应用程序 "upload" 目录的绝对路径。
  • FLET_MAX_UPLOAD_SIZE - 允许上传文件的最大大小,以字节为单位。如果未指定,则不受限制。
  • FLET_SECRET_KEY - 签署临时上传 URL 的密钥。
  • FLET_WEB_APP_PATH - 域名后的 URL 路径,用于托管 Web 应用程序,例如 /apps/myapp。默认是 / - 在根目录下托管应用程序。
  • FLET_SESSION_TIMEOUT - 会话的生命周期,以秒为单位。默认是 3600
  • FLET_OAUTH_STATE_TIMEOUT - 完成 OAuth Web 流程的最长允许时间,以秒为单位。默认是 600
  • FLET_WEB_RENDERER - Flutter 渲染模式:canvaskit(默认),htmlauto
  • FLET_WEB_USE_COLOR_EMOJI - 设置为 trueTrue1 以加载带有彩色表情符号的 Web 字体。
  • FLET_WEB_ROUTE_URL_STRATEGY - path(默认)或 hash
  • FLET_WEBSOCKET_HANDLER_ENDPOINT - WebSocket 处理程序的自定义路径。默认是 /ws
  • FLET_UPLOAD_HANDLER_ENDPOINT - 上传处理程序的自定义路径。默认是 /upload
  • FLET_OAUTH_CALLBACK_HANDLER_ENDPOINT - OAuth 处理程序的自定义路径。默认是 /oauth_callback

异步优先框架

Flet 现在是一个异步优先框架,这意味着你不必决定你的应用程序是完全同步还是异步,你可以在同一个应用程序中混合使用同步和异步方法。

例如,在 Flet 0.21.0 中,你可以这样编写一个应用程序:

import flet as ft
import time
import asyncio

def main(page: ft.Page):

def handler(e):
time.sleep(3)
page.add(ft.Text("Handler clicked"))

async def handler_async(e):
await asyncio.sleep(3)
page.add(ft.Text("Async handler clicked"))

page.add(
ft.ElevatedButton("Call handler", on_click=handler),
ft.ElevatedButton("Call async handler", on_click=handler_async)
)

ft.app(main)

在上面的示例中,点击一个按钮由“阻塞”处理程序处理,而点击第二个按钮调用异步处理程序。第一个处理程序在threading.Thread中运行,而第二个处理程序在asyncio.Task中运行。

此外,请注意在async def处理程序中不再需要使用await page.add_async(),而是可以使用常规的page.add()

API变更

大多数Page.<method>_async()Control.<method>_async()方法已被弃用,应使用其Page.<method>()Control.<method>()对应方法。

唯一的例外是返回结果的方法,例如Audio控制中的那些方法:在异步事件处理程序中仍然必须使用异步方法。

自定义控件 API 规范化

在这个 Flet 版本中,我们还重新审视了在 Python 中编写自定义控件的 API。

因此,UserControl类已被弃用。你只需继承具有适合你需求的布局的特定控件。

例如,Countdown自定义控件只是一个Text,可以如下实现:

import asyncio

import flet as ft

class Countdown(ft.Text):
def __init__(self, seconds):
super().__init__()
self.seconds = seconds

def did_mount(self):
self.running = True
self.page.run_task(self.update_timer)

def will_unmount(self):
self.running = False

async def update_timer(self):
while self.seconds and self.running:
mins, secs = divmod(self.seconds, 60)
self.value = "{:02d}:{:02d}".format(mins, secs)
self.update()
await asyncio.sleep(1)
self.seconds -= 1

def main(page: ft.Page):
page.add(Countdown(120), Countdown(60))

ft.app(main)

注意使用self.page.run_task(self.update_timer)启动新任务。 控件开发者还必须使用self.page.run_thread()方法在线程中启动新后台作业。

如果你想生成自己的任务或线程,Flet通过Page.loopPage.executor属性分别提供当前事件循环和线程执行器。

API变更

Control._before_build_command()Control.before_update()取代

Control.build()现在不应返回任何控件,而必须更新继承的控件属性,例如:

def build():
self.controls.append(ft.Text("Something"))

Control.did_mount_async()Control.will_unmount_async()已被弃用。请使用Control.did_mount()Control.will_unmount()

新的Cupertino控件

此Flet版本添加了更多Cupertino控件,使你的应用在iOS上更加出色:

  • CupertinoActivityIndicator
  • CupertinoActionSheet
  • CupertinoSlidingSegmentedButton
  • CupertinoSegmentedButton
  • CupertinoTimerPicker
  • CupertinoPicker
  • CupertinoDatePicker
  • CupertinoContextMenu

无障碍性改进

现在Flet已经完全实现了Semantics控件和新的SemanticsService控件。

应用生命周期更改事件

新增了 Page.on_app_lifecycle_state_change 事件,允许监听应用程序生命周期的变化。

例如,当应用变为活动状态(切换到前台)时,你现在可以使用最新信息更新UI。此事件适用于iOS、Android、所有桌面平台和Web!

以下是识别的应用程序生命周期转换:

  • SHOW
  • RESUME
  • HIDE
  • INACTIVE
  • PAUSE
  • DETACH
  • RESTART
备注

阅读有关每个生命周期状态的更多信息。

这是一个如何使用此事件的小示例:

import flet as ft

def main(page: ft.Page):

def app_lifecycle_change(e: ft.AppLifecycleStateChangeEvent):
if e.state == ft.AppLifecycleState.RESUME:
print("Update UI with fresh data!")

page.on_app_lifecycle_state_change = app_lifecycle_change
page.add(ft.Text("Hello World"))

ft.app(target=main)

Flet 0.21.0版本有一些重大变化。升级到它,测试你的应用,并让我们知道它的运行情况。加入Flet Discord服务器或在Flet GitHub讨论区创建一个新话题。

祝你愉快!

Flet 自适应 UI 和自定义控件发布

· 阅读需 5 分钟
Feodor Fitsner
Flet 创始人和开发者

🥰 情人节快乐,亲爱的朋友们!🥰

我们刚刚发布了 Flet 0.20.0,重点如下:

  1. 自适应 UI。
  2. 使用第三方 Flutter 包扩展 Flet 应用。
  3. 新控件:Video(耶!)、AudioRecorder 和一系列 Cupertino 风格控件。Flet 现在包含 97 个内置控件!
注意

Flet 0.20.0 包含一个新的 Video 控件。虽然 macOS 和 Windows 已经包含所有测试 Flet 应用所需的媒体库,但在 Linux 上需要安装 libmpv 包。在 Ubuntu/Debian 上可以通过以下命令安装:

sudo apt install libmpv-dev mpv

自适应 UI

自适应控件允许编写具有单个代码库的应用程序,这些应用程序在运行的平台不同时具有不同的外观和行为。

截至目前,Flet 提供了 [11 个自适应控件]。要使控件自适应,可以将其 adaptive 属性设置为 True

在 Flet 0.20.0 中,我们为所有类似容器的控件引入了 adaptive 属性。 在容器上设置 adaptive=True 会将此属性传播到所有子自适应控件。

Page 添加了 design 属性,使您可以对控件的设计语言进行细粒度控制,其值可以为:ft.PageDesign.ADAPTIVEft.PageDesign.MATERIALft.PageDesign.CUPERTINO

只需设置 page.design = ft.PageDesign.ADAPTIVE,即可使您的应用在 iOS 和 Android 设备上看起来都很棒:

iPhone

Android

集成现有的 Flutter 包

目前 Flet 提供了近 100 个控件,但如您所想,并不是每个 Flutter 库/小部件都可以添加到核心 Flet 库中,Flet 团队也无法在可接受的时间范围内独自完成。

同时,我们也不希望让选择 Flet 来构建其下一个商业或企业应用的早期采用者处于他们的进展依赖于 Flet 团队是否有时间和愿意实现他们所需的 Flutter 控件的情况。

在 Flet 0.20.0 中,我们重新构建了 Flutter 核心包,并确定了可供第三方开发者使用的 API 来添加他们自己的用 Dart 编写的 Flet 控件。

我们目前正在编写 API 文档,但您现在可以通过查看 VideoAudio 控件的 Dart 源代码来了解如何实现自定义 Flutter 包。

简而言之,您需要创建一个新的 Flutter 包,其中包含并导出两个方法:

void ensureInitialized();
Widget createControl(CreateControlArgs args);

参见 ensureInitialized()createControl()Video 控件实现。

在 Python 方面,您需要创建一个从 Control(非可视或叠加控件)或 ConstrainedControl 继承的新类。

参见 Python 中 Video 类的实现。

要在构建 Flet 应用时集成自定义 Flutter 包,使用 flet build 命令,您可以使用 --include-packages 选项或在 Flet 应用根目录下的 pubspec.yaml 文件中列出额外的包。

Video 控件

Video 控件在一个单独的 Flutter 包中实现。

要构建包含 Video 控件的 Flet 应用,请在 flet build 命令中添加 --include-packages flet_video,例如:

flet build apk --include-packages flet_video

Flet 0.20.0 是一个相对较大的 版本,可能会破坏一些东西。

升级到 Flet 0.20.0,测试您的应用,并通过加入 Flet Discord 服务器 或在 Flet GitHub 讨论 中创建新线程来告诉我们您的想法。

祝您愉快!

将应用打包进行分发

· 阅读需 4 分钟
Feodor Fitsner
Flet 创始人兼开发者

亲爱的朋友们!在今年的最后一篇文章中,我想感谢大家对 Flet 项目的贡献,无论是散发信息,提交拉取请求,加入 Discord 讨论还是发送烦人的错误报告!

在你们的极好支持下,我们在 2023 年取得了很多成就:

  • 70 多个控件(特别感谢 @ndonkoHenri 的巨大贡献)。
  • GitHub 上获得 7,700 颗星。
  • Discord 上有 2,150 名用户和社区版主(感谢你们!)。
  • Flet 与 Pyodide 的集成,用于纯客户端的 Python 应用——没有其他框架能为 Pyodide 提供更好的用户界面!
  • Flet 应用已上线 AppStore 和 Google Play——这是在移动设备上测试的好方法,也是 Flet 应用被接受的实际证明。
  • ……最后……隆重宣布……🥁🥁🥁 flet build 命令来了!🎉🎉🎉

🎄 "新年版" 🎄 的 Flet 0.18.0 刚刚发布,这个版本允许在所有平台上打包您的 Flet 应用进行分发:iOS、Android、Web、macOS、Windows 和 Linux!

一个命令玩转所有!

现在闭环完成了:您可以使用 Flet CLI 创建 (flet create)、运行 (flet run) 和构建 (flet build) 您的 Flet 应用。

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

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

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

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

查看 打包应用以便分发 指南,获取关于 flet build 命令的完整信息。

请通过加入 Flet Discord 服务器 或在 Flet GitHub 讨论区 创建新话题,让我们知道您的想法。

祝大家新年快乐!节日愉快!

Flet为FastAPI提供支持

· 阅读需 3 分钟
Feodor Fitsner
Flet 创始人和开发者

我们刚刚发布了支持 FastAPI 的 Flet 0.10.0!

FastAPI 配合 Uvicorn、Hypercorn、Gunicorn 或其他网络服务器,可以取代内置的 Flet 网络服务器(Fletd),以可靠地运行生产环境中的 Flet 工作负载。

另一方面,经验丰富的 FastAPI 开发者可以使用 Flet,轻松地为现有或新的 FastAPI 服务添加互动的实时仪表盘和管理 UI。

一个简单的应用示例

import flet as ft
import flet_fastapi

async def main(page: ft.Page):
await page.add_async(
ft.Text("Hello, Flet!")
)

app = flet_fastapi.app(main)

这是一个简单的应用程序,只是在网页上输出“Hello, Flet!”。

要运行该应用程序,请安装 Flet for FastAPI 和 Uvicorn:

pip install flet-fastapi
pip install uvicorn

将上述代码保存为 hello.py,然后启动 Uvicorn:

uvicorn hello:app

打开浏览器并导航到 http://127.0.0.1:8000 查看运行中的应用程序。

警告

Flet 应用程序必须是 异步的 才能与 FastAPI WebSocket 处理程序一起工作。

特性和优势

  • 单域名下的多个 Flet 应用程序 - 映射到根路径和/或子路径。
  • 简单的单行映射单个端点配置
  • 围绕 FastAPI WebSocket 连接的轻量级异步包装器,以提高并发性。
  • 提供包含用户资源和应用程序元信息自定义的 Flet 静态文件。
  • FilePicker 控件的上传处理程序。
  • 处理 OAuth 回调进行身份验证流程。

查看 指南 以获取有关 Flet 与 FastAPI 的完整信息。

通过加入 Flet Discord 服务器 或在 Flet GitHub 讨论 创建新主题,让我们知道您的想法。

用于 Android 的 Flet

· 阅读需 3 分钟
Feodor Fitsner
Flet创始人兼开发者

🤖 现已支持Android平台!

通过 Flet Android 应用,你可以在 Android 设备上查看 Flet Python 应用的外观和行为,而应用本身仍在你的电脑上运行。

与 iOS 类似,Flet for Android 是一个完全用 Python 编写的 Flutter 应用,使用了两个开源软件包:serious_pythonflet。生成的应用包技术上符合 Google Play 的要求,因此你可以用纯 Python 发布优秀的 Android 应用。

按照本指南 开始在 Android 上测试你的 Flet 应用。探索应用、浏览画廊、尝试示例项目和应用设置。

常见问题

如何将我的 Flet 应用打包到 Google Play?

我们将提供一个启动 Flutter 应用的项目模板和指南,介绍如何将 Flutter、serious_python 软件包和你的 Python 应用结合在一起,创建一个独立的 Android 应用并发布到 Google Play。

查看 serious_python 的自述文件,了解如何创建一个 Flutter 启动并将你的 Python 应用打包在其中。使用 flet_example 项目作为起点。

你们会提供 Windows、macOS 和 Linux 的打包吗?

会的!目前,Flet 桌面应用使用 flet pack 命令和 PyInstaller 打包。生成的应用包增加了性能和大小的开销,并且难以定制,因此我们将用原生的 Flutter 打包替代它。

Flet v0.9.0 发行说明

要在 Android 上进行测试,你需要将 Flet 安装升级到 v0.9.0。

为了支持 Android,Flet CLI 进行了一些更改。如果你发现了什么异常情况,请告诉我们。

祝您使用愉快!