EEL 启动流程
-
初始化 EEL (
eel.init()
):- 设定静态文件目录,通常是包含 HTML、CSS、JavaScript 等文件的目录。
- 扫描指定目录下的 JavaScript 文件,寻找通过
eel.expose()
暴露的函数。
-
启动 Web 服务器 (
eel.start()
):- 基于 Bottle 框架启动一个轻量级的 Web 服务器。
- 服务器配置默认主页和静态资源的服务。
-
创建 WebSocket 服务:
- 通过 Bottle 的插件或扩展来启动 WebSocket 服务。
- WebSocket 用于支持浏览器(客户端)与 Python(服务器)之间的实时双向通信。
-
创建对应的 Python 函数:
- 根据扫描到的暴露的 JavaScript 函数,动态创建 Python 中的对应函数,这些函数可用于从 Python 端调用 JavaScript 函数。
-
打开浏览器窗口(可选):
- 如果配置了 EEL 以特定模式运行(如 Chrome 应用模式),EEL 可以自动打开一个浏览器窗口并加载应用。
-
WebSocket 连接:
- 客户端(浏览器)加载页面后,通过 EEL 的 JavaScript 部分建立 WebSocket 连接到服务器。
- WebSocket 连接保持开启状态,等待来自客户端的调用或发送到客户端的数据。
- 初始化阶段:设置基本配置,包括文件目录和 JavaScript 函数扫描,是启动过程的前提。
- Web 服务器和 WebSocket:这两个组件是并行启动的,服务器处理静态文件请求,而 WebSocket 负责处理实时的数据交互。
- 用户交互:一旦浏览器窗口打开,用户可以开始与应用交互,所有的前端调用都通过 WebSocket 传输到后端,并接收来自后端的响应。
为什么eel.init()之后,eel.start()之前就可以在python端通过eel.js_function_name()调用前端的js函数?并且调用的结果能在启动的界面中呈现出来,此时web服务器还未启动呢!官方文档的例子eel.say_hello_js('Python World!') 就在 eel.start('hello.html')之前。
import eel
# Set web files folder and optionally specify which file types to check for eel.expose()
# *Default allowed_extensions are: ['.js', '.html', '.txt', '.htm', '.xhtml']
eel.init('web', allowed_extensions=['.js', '.html'])
@eel.expose # Expose this function to Javascript
def say_hello_py(x):
print('Hello from %s' % x)
say_hello_py('Python World!')
eel.say_hello_js('Python World!') # Call a Javascript function
eel.start('hello.html') # Start (this blocks and enters loop)
这其实是EEL的排队机制在管理这些js_function调用。
EEL的队列工作机制
在 EEL 中,当你调用一个 JavaScript 函数,如 eel.say_hello_js('Python World!')
,这个调用实际上并不是立即执行的。这个调用是放入一个队列中的,然后在 EEL 的 WebSocket 连接建立后才真正执行。eel.start()
函数负责启动服务器、设置 WebSocket 通信,并处理事件循环。在事件循环中,之前队列中的 JavaScript 调用会被发送到客户端执行。
这意味着,尽管 Python 代码中的调用顺序是在启动服务器之前,但 JavaScript 函数的执行仍然依赖于页面的加载和 WebSocket 连接的建立。
开发者的意图
这种设计允许开发者在代码中以一种直观的方式安排调用顺序,而无需担心实际的通信延迟。EEL 库内部处理了调用的延迟执行,确保所有事务都在正确的时间点上正确发生,即在页面准备好后。
实际应用中的注意事项
- 阻塞与非阻塞模式:
eel.start()
默认是阻塞模式,它会启动一个事件循环并等待浏览器连接。如果需要在启动后执行其他 Python 代码,可以设置block=False
。 - 调用的顺序:尽管 Python 代码中看起来是先调用
eel.say_hello_js()
,但这些调用只有在浏览器页面加载后才真正执行。