pywebview/eel 跨窗口通信:如何实现单窗口触发操作并在另一窗口执行
pywebview/eel 多窗口通信最简实现方案
pywebview 实现(无需额外socket服务)
pywebview 原生内置了跨窗口通信能力,完全不需要搭建Flask-SocketIO这类额外网络服务,核心用到两个自带能力:
js_api绑定:把Python方法暴露给指定窗口的前端,供前端触发调用- 窗口实例的
evaluate_js方法:直接在对应窗口的渲染上下文里执行任意JS代码,完成DOM操作或其他逻辑
完整可运行代码
import webview import json # 全局存储所有窗口实例,方便Python端内部调用 window_map = {} def update_second_window(target_text): """供窗口1前端调用的Python方法,用于修改窗口2的内容""" second_win = window_map.get('second') # 先判断窗口2是否存在,避免调用已关闭窗口的接口报错 if second_win and second_win.exists(): # 用JSON序列化转义特殊字符,避免JS语法错误 js_code = f'document.getElementById("target").innerText = JSON.parse(\'{json.dumps(target_text)}\')' second_win.evaluate_js(js_code) if __name__ == '__main__': # 窗口1的页面内容:加触发按钮 master_html = ''' <h1>First window</h1> <button onclick="handleClick()">点击更新窗口2内容</button> <script> async function handleClick() { // 调用Python端暴露的方法 await pywebview.api.update_second_window('这是从窗口1传来的自定义文本') } </script> ''' # 窗口2的页面内容:加待修改的目标元素 second_html = ''' <h1>Second window</h1> <p id="target">窗口2的默认初始内容</p> ''' window_map['master'] = webview.create_window( title='Window #1', html=master_html, js_api=update_second_window # 把Python方法绑定到窗口1的前端上下文 ) window_map['second'] = webview.create_window('Window #2', html=second_html) webview.start()
注意事项
- 传递包含特殊字符的文本时,必须用
json.dumps做转义,避免JS语法错误或安全问题 - 调用
evaluate_js前一定要判断目标窗口是否存在,否则操作已关闭的窗口会抛出异常 - 如果不想把方法全局暴露给所有窗口,直接在对应窗口的
create_window调用时通过js_api参数传入即可,只会绑定到当前窗口的前端上下文
eel 实现(无需自建Socket服务)
eel 本身已经内置了轻量WebSocket通信能力,不需要额外搭建Flask-SocketIO这类服务,直接通过Python中转即可实现跨窗口调用:
- 先把窗口2要执行的JS函数暴露给eel,供Python端调用
- 写一个Python方法暴露给窗口1的前端,窗口1按钮点击时触发这个Python方法,Python端再调用窗口2暴露的JS函数即可
示例代码
首先是Python端逻辑:
import eel # 初始化eel静态资源目录,存放各个窗口的html文件 eel.init('web') # 暴露给窗口1前端调用的Python方法 @eel.expose def trigger_update_second_win(text): # 直接调用窗口2中暴露的JS函数 eel.update_target_text(text)() # 启动时指定两个窗口页面,eel会自动弹出两个窗口 eel.start(['window1.html', 'window2.html'], size=(400, 300))
对应窗口2的html(放在web/window2.html)里需要先把要执行的JS函数暴露给eel:
<h1>Second window</h1> <p id="target">窗口2默认内容</p> <script> // 把JS函数暴露给Python端调用 eel.expose(update_target_text); function update_target_text(text) { document.getElementById('target').innerText = text; } </script>
窗口1的html(放在web/window1.html)里加触发按钮:
<h1>First window</h1> <button onclick="handleClick()">更新窗口2内容</button> <script> async function handleClick() { await eel.trigger_update_second_win('从窗口1传来的文本'); } </script>
内容的提问来源于stack exchange,提问作者Amin Pial
相关产品推荐
相关产品推荐

