
Flet 应用在 Spyder、Jupyter 或其他已启动 asyncio 事件循环的 IDE 中直接调用 ft.app() 会报错“RuntimeError: asyncio.run() cannot be called from a running event loop”,需改用 loop.run_until_complete() 手动接管并兼容现有循环。
flet 应用在 spyder、jupyter 或其他已启动 asyncio 事件循环的 ide 中直接调用 `ft.app()` 会报错“runtimeerror: asyncio.run() cannot be called from a running event loop”,需改用 `loop.run_until_complete()` 手动接管并兼容现有循环。
Flet 是一个用于构建跨平台桌面与 Web UI 的 Python 框架,其核心 ft.app() 函数内部默认调用 asyncio.run() 启动主事件循环。然而,Spyder(尤其是 5.5+ 版本)、Jupyter Notebook、VS Code 的 Python Interactive 窗口等开发环境自身已运行着一个 asyncio 事件循环——此时再调用 asyncio.run() 就会触发 Python 的明确限制,抛出 RuntimeError。
✅ 正确解决方案是:绕过 ft.app() 的自动事件循环管理,手动获取当前事件循环并调度 Flet 应用。以下是推荐的稳健写法:
import asyncio
import flet as ft
async def main(page: ft.Page):
page.title = "Flet counter example"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
txt_number = ft.TextField(value="0", text_align=ft.TextAlign.RIGHT, width=100)
def minus_click(e):
txt_number.value = str(int(txt_number.value) - 1)
page.update()
def plus_click(e):
txt_number.value = str(int(txt_number.value) + 1)
page.update()
page.add(
ft.Row(
[
ft.IconButton(ft.icons.REMOVE, on_click=minus_click),
txt_number,
ft.IconButton(ft.icons.ADD, on_click=plus_click),
],
alignment=ft.MainAxisAlignment.CENTER,
)
)
if __name__ == "__main__":
# 安全获取当前事件循环(兼容 Python 3.7+)
try:
loop = asyncio.get_running_loop()
except RuntimeError: # 无运行中 loop 时 fallback
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
if loop.is_running():
print("⚠️ 当前环境已存在运行中的事件循环(如 Spyder/Jupyter)")
print(" 建议:1) 在终端中执行 'python script.py';或")
print(" 2) 使用下方兼容方式启动(仅限调试)")
# 注意:ft.app() 不支持在运行中的 loop 内直接 await,
# 但可借助 threading 或 subprocess 实现隔离 —— 生产环境不推荐
import sys
print(f"? 提示:当前 Python 可执行文件路径为 {sys.executable}")
print(" 可在终端中运行:", sys.executable, __file__)
else:
# 标准启动路径(适用于命令行/独立终端)
loop.run_until_complete(ft.app(target=main))? 关键注意事项:
- ❌ 不要强行在 asyncio.get_event_loop().run_until_complete() 中调用 ft.app(...) 并期望它阻塞当前线程 —— Flet 的 ft.app() 本身会尝试接管控制权,与 IDE 的 UI 线程易冲突;
- ✅ 最可靠方式始终是脱离 IDE 运行:在系统终端(Windows Terminal / macOS Terminal / Linux Shell)中执行 python counter.py;
- ? 若必须在 Spyder 中调试逻辑,可将 UI 部分注释掉,单独测试 main() 中的业务函数(如 minus_click),再整体移至终端验证;
- ? 避免使用 nest_asyncio 等补丁方案——虽能“绕过”报错,但可能导致 Flet 渲染异常、热重载失效或资源泄漏,不符合官方实践。
总结:Flet 设计初衷是作为独立应用运行,而非嵌入式组件。遇到事件循环冲突时,优先选择终端执行;若需 IDE 协作开发,请将 UI 启动逻辑与业务逻辑解耦,确保可测试性与部署一致性。

















