ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

NiceGUI 集成 websockets 库:为外部非 NiceGUI 客户端开放 WebSocket 服务

2026/9/14 5:24:08 拓冰建站 浏览量
NiceGUI 集成 websockets 库:为外部非 NiceGUI 客户端开放 WebSocket 服务 NiceGUI 集成 websockets 库为外部非 NiceGUI 客户端开放 WebSocket 服务【免费下载链接】niceguiCreate web-based user interfaces with Python. The nice way.项目地址: https://gitcode.com/GitHub_Trending/ni/nicegui本文以仓库中 examples/websockets/README.md 文档为骨架深入讲解如何利用websockets库在 NiceGUI 应用中启动一个独立的 WebSocket 服务器接收来自非 NiceGUI 客户端的连接与消息并通过 NiceGUI 的Event事件机制将连接状态与消息实时同步到网页界面。读完本文你将掌握在 NiceGUI 中集成第三方 WebSocket 服务的完整实战方案包括服务器启动、连接管理、消息广播与 UI 联动。在绝大多数场景下NiceGUI 已经通过内置的 Socket.IO 机制替开发者处理了浏览器与服务器之间的所有实时通信你无需关心 WebSocket 的底层细节。但当你希望允许非 NiceGUI 客户端例如命令行脚本、嵌入式设备、其他语言编写的程序直接连入你的服务端时就需要借助websockets库自行启动一个标准的 WebSocket 服务端点。这正是examples/websockets示例的存在意义。一、示例概览与适用场景examples/websockets目录下的示例演示了一条完整的数据通路NiceGUI 应用启动时在后台额外启动一个独立的 WebSocket 服务器监听localhost:8765任何使用 WebSocket 协议的外部客户端都可以连接该端口网页端实时显示当前连接数、接收到的所有客户端消息点击网页上的按钮可以向所有已连接的外部客户端广播消息。整个示例的核心代码位于 examples/websockets/main.py依赖声明位于 examples/websockets/requirements.txt。从源码顶部的注释可以确认其设计定位NiceGUI already handles all the communication for you, so you dont need to worry about websockets and the like normally. This example is only for advanced use cases where you want to allow other, non-NiceGUI clients to connect to your server.即这是面向高级用例的示例适用场景包括但不限于让命令行脚本、传感器设备等非浏览器客户端向 NiceGUI 应用上报数据在 NiceGUI 页面中监控实时连接状态与消息流将 NiceGUI 页面作为控制台/监控面板向外部客户端下发指令。二、环境准备与依赖版本示例通过 examples/websockets/requirements.txt 声明了两个依赖nicegui3.0 websockets 12.0其中nicegui3.0示例使用了 NiceGUI 3.x 的 API包括ui.page、ui.number、ui.log、app.on_startup以及nicegui.Event事件机制websockets 12.0本示例依赖websockets库的serve、broadcast等高级 API并要求ServerConnection类型注解可用websockets.server.ServerConnection从该版本起稳定提供。安装依赖后直接运行即可pip install -r examples/websockets/requirements.txt python examples/websockets/main.py三、核心实现逐段拆解3.1 全局连接集合与事件总线示例在模块顶部定义了三个全局对象它们构成了整个示例的数据中枢import asyncio import websockets from websockets.server import ServerConnection from nicegui import Event, app, ui CONNECTIONS: set[ServerConnection] set() connections_updated Event() message_received Event()CONNECTIONS一个set[ServerConnection]保存当前所有存活的外部 WebSocket 连接用于后续的计数展示与广播connections_updated/message_received两个nicegui.Event实例。这是 NiceGUI 3.x 提供的事件分发工具用于将长生命周期对象这里是后台 WebSocket 服务器产生的状态变化安全地传递给短生命周期的 UI 元素页面刷新即销毁。之所以引入Event是因为 WebSocket 服务器的生命周期与网页客户端的生命周期完全不同服务器常驻后台而页面元素会随用户刷新、断开而重建。通过订阅subscribe与触发emit机制两者得以解耦。从源码 nicegui/event.py 可以看出Event.subscribe会记录回调函数、自动探测回调是否需要接收参数expect_args并且当订阅发生在 UI 上下文内时会自动在客户端被删除时取消订阅unsubscribe_on_delete从而避免内存泄漏——这正是它适合做后台到 UI 通知的原因。3.2 网页端 UI展示连接状态与消息流ui.page(/) def page(): ui.markdown( # Websockets Example Run this in the console to connect: bash python -m websockets ws://localhost:8765/ ) count ui.number(valuelen(CONNECTIONS), suffixconnections).props(readonly).classes(w-32) connections_updated.subscribe(lambda: count.set_value(len(CONNECTIONS))) ui.label(Incoming messages:) messages ui.log() message_received.subscribe(messages.push) ui.button(Send hello, on_clicklambda: websockets.broadcast(CONNECTIONS, Hello!))页面结构分为四个部分连接指引页面直接用ui.markdown展示了一条可复制执行的客户端连接命令详见下文第四节帮助外部客户端使用者快速接入连接数显示ui.number初始值取自len(CONNECTIONS)并通过connections_updated.subscribe(...)订阅事件——每当有连接加入或断开回调会更新计数。props(readonly)使其成为只读展示框消息日志ui.log()创建一个带滚动条的日志组件message_received.subscribe(messages.push)将每条收到的消息追加进去。注意这里直接把messages.push方法作为回调传入依赖Event对回调签名的自动探测见 nicegui/event.py广播按钮点击按钮触发websockets.broadcast(CONNECTIONS, Hello!)这是websockets库 12.0 提供的便捷 API可一次性向集合中的全部连接推送同一条消息。3.3 应用启动时拉起 WebSocket 服务器app.on_startup async def start_websocket_server(): async with websockets.serve(handle_connect, localhost, 8765): await asyncio.Future()这是示例中关键的一步通过app.on_startup注册一个异步启动钩子在 NiceGUI 启动时同步拉起 WebSocket 服务器。websockets.serve(handle_connect, localhost, 8765)在localhost:8765上启动 WebSocket 服务器每个新连接都会调用handle_connect处理器await asyncio.Future()一个永不完成的 Future让async with上下文即服务器在应用整个生命周期内保持运行app.on_startup是 nicegui/app/app.py 中App.on_startup的生命周期钩子要求必须在ui.run()之前注册且支持同步/异步回调。NiceGUI 在App.start()见 nicegui/app/app.py中通过safe_invoke执行这些钩子异步结果会被包装为后台任务。3.4 连接处理器注册、转发、清理async def handle_connect(websocket: ServerConnection): Register the new websocket connection, handle incoming messages and remove the connection when it is closed. try: CONNECTIONS.add(websocket) connections_updated.emit() async for message in websocket: message_received.emit(str(message)) finally: CONNECTIONS.remove(websocket) connections_updated.emit()handle_connect是每个外部连接的生命周期处理器逻辑分为三个阶段连接加入将websocket加入CONNECTIONS集合并emit连接更新事件网页上的连接数随之 1消息循环通过async for message in websocket异步迭代接收该连接发来的每一条消息并触发message_received.emit(str(message))将消息推送到网页日志。这里将消息显式转为str保证二进制帧等非文本数据也能被 UI 安全处理连接清理finally块保证无论连接是正常关闭还是异常断开都会从集合中移除并再次触发更新事件网页连接数随之 -1不会产生残留的失效连接。值得一提的是Event.emit见 nicegui/event.py是即发即忘式的它不会等待回调完成同步回调会被直接执行异步回调则交由 nicegui/background_tasks.py 的background_tasks.create包装为任务并挂接全局异常处理器。因此从 WebSocket 消息循环里高频emit也不会阻塞消息接收。四、运行示例并连接外部客户端4.1 启动服务端在仓库根目录执行python examples/websockets/main.pyNiceGUI 会启动网页服务默认http://localhost:8080可用ui.run(port...)调整参数定义见 nicegui/ui_run.py同时后台 WebSocket 服务器监听ws://localhost:8765/。4.2 使用命令行客户端连接打开另一个终端执行页面中提示的命令python -m websockets ws://localhost:8765/这是websockets库自带的一个简单的交互式命令行客户端连接建立后服务端页面上的连接计数会立即变为 1在命令行中输入任意文本并回车消息会实时出现在网页的 Incoming messages 日志中点击网页上的Send hello按钮命令行终端会收到推送的Hello!消息。4.3 连接多个客户端验证广播可以同时打开多个终端执行上述命令验证每个新连接都会让网页计数递增断开按CtrlC后计数递减点击一次Send hello所有已连接的客户端都会收到Hello!——这正是websockets.broadcast(CONNECTIONS, Hello!)的效果。五、进阶要点与注意事项监听地址示例将服务器绑定在localhost:8765因此只能接受本机连接。若要允许局域网或其他主机的外部客户端接入需要改为websockets.serve(handle_connect, 0.0.0.0, 8765)或指定具体网卡地址同时注意防火墙与安全边界端口冲突8765是示例采用的固定端口若被占用会启动失败可自行调整自动重载的兼容性NiceGUI 的ui.run(reloadTrue)默认开启会在代码变更时重启应用app.on_startup钩子会随之重新执行WebSocket 服务器也会被重新拉起App.on_startup内部对 script 模式的重执行做了幂等处理见 nicegui/app/app.py避免重复注册线程模型websockets.serve运行在 NiceGUI 的 asyncio 事件循环中启动钩子本身是异步的因此emit事件、UI 更新与 WebSocket 收发天然共享同一个事件循环无需额外的线程同步消息安全async for收到的消息会被原样推送到网页日志若外部客户端不受信建议在handle_connect中增加消息校验/过滤逻辑后再emit避免将恶意内容直接渲染到 UI。六、小结examples/websockets示例给出了一个清晰可复用的模式用app.on_startup在 NiceGUI 应用内嵌一个独立的websockets服务器用set[ServerConnection]管理连接集合用nicegui.Event将后台连接与消息事件桥接到页面 UI并用websockets.broadcast实现一键群发。整个链路不依赖任何额外的中间件或数据库代码不足 60 行即可完成外部客户端 ↔ NiceGUI 监控面板的双向通信。对于更复杂的实时应用还可以参考仓库中同类的通信类示例如 examples/websocketsSocket.IO 浏览器端通信、examples/chat_app聊天室与 examples/global_worker全局后台任务与 UI 交互它们共同构成了 NiceGUI 异步实时通信的完整实践图谱。【免费下载链接】niceguiCreate web-based user interfaces with Python. The nice way.项目地址: https://gitcode.com/GitHub_Trending/ni/nicegui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考