跳到主要内容

异步应用

Flet 应用可以编写为异步应用,并使用 asyncio 和其他 Python 异步库。在 Flet 中,调用协程是自然支持的,因此您无需将它们包装成同步运行。

默认情况下,Flet 在单独的线程中执行控制事件处理程序,但有时这可能会是对 CPU 的低效使用,或者在等待 HTTP 响应或执行 sleep() 时没有任何作用。

另一方面,Asyncio 允许在单个线程中通过在 "协程" 之间切换执行上下文来实现并发。这对于将应用程序发布为静态网站并使用 Pyodide 的情况尤其重要。Pyodide 是一个构建为 WebAssembly(WASM)并在浏览器中运行的 Python 运行时。在撰写本文时,它尚不支持线程

开始使用异步

您可以将 Flet 应用的 main() 方法标记为 async,然后在其中使用任何 asyncio API:

import flet as ft

async def main(page: ft.Page):
await asyncio.sleep(1)
page.add(ft.Text("你好,异步世界!"))

ft.app(main)

如果 Flet 应用是较大应用的一部分,并且从 async 代码中调用,则可以使用 await ft.app_async(main)

控制事件处理程序

控制事件处理程序可以是同步的也可以是 async 的。

如果处理程序不调用任何异步方法,则可以是常规同步方法:

def page_resize(e):
print("新页面尺寸:", page.window.width, page.window.height)

page.on_resize = page_resize

但是,如果处理程序调用异步逻辑,则它必须是异步的:

async def main(page: ft.Page):

async def button_click(e):
await some_async_method()
page.add(ft.Text("你好!"))

page.add(ft.ElevatedButton("说个你好!", on_click=button_click))

ft.app(main)

异步 lambda 表达式

Python 中没有异步 lambda 表达式。对于简单的事情,在异步应用中使用 lambda 事件处理程序是完全可以的:

page.on_error = lambda e: print("页面错误:", e.data)

但是您不能有异步 lambda,因此必须使用异步事件处理程序。

睡眠

在异步 Flet 应用中延迟代码执行应使用 asyncio.sleep(),例如:

import asyncio
import flet as ft

def main(page: ft.Page):
async def button_click(e):
await asyncio.sleep(1)
page.add(ft.Text("你好!"))

page.add(
ft.ElevatedButton("延迟说个你好!", on_click=button_click)
)

ft.app(main)

线程

要在后台运行某些内容,请使用 page.run_task()。例如,可将 "倒计时" 自定义控件实现为在后台自更新的内容:

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)