什么邪道?Electron 框架中调用 Python 构建桌面应用!
为什么想在 Electron 中调用 Python
不同的语言、框架都有自己擅长的领域:Electron 基于 Chromium 和 Node.js 能以 Web 开发的模式打造桌面应用,开发用户界面又快捷又简单;Python 则在数据分析、自动化脚本等领域有非常多的应用。两者的社区生态都十分强大,由两者共同构建应用,在界面开发、功能、性能上能够强强联合;
为了简单验证技术可行性,我们来编写一个 Demo:
Demo 说明
目的:验证 Electron 打造的桌面应用能够调用 Python,思路是使用 RPC 或 HTTP 或 WebSocket 进行通信
Demo 功能:输入 x、y 坐标,程序会移动鼠标到屏幕的 x,y 位置(通过 python 库 pyautogui 实现)
Demo 运行环境:MacOS、pyInstaller: 版本 4.5.1、python: 版本 3.9.7
源码:-------- 项目源码 --------
注意:移动鼠标需要授予应用控制权限,在 MacOS 下设置 偏好设置 -> 隐私 -> 辅助功能 -> 允许对应的应用。
技术栈:NodeJS、Electron、Python、aiohttp(HTTP、WebSocket)、pyautogui(控制鼠标)
如何实现两者的通信
为了使 NodeJS 和 Python 能够通信,Python 需要启动一个本地通信服务,Demo 中 py/api.py
能够启动一个本地 HTTP 服务:
from aiohttp import web
import controller
app = web.Application()
app.add_routes([web.get('/controlMouseAndKeyboard', controller.controlMouseAndKeyboard),
web.get('/t', controller.test),
web.get('/ws', controller.websocket_handler)])
if __name__ == '__main__':
web.run_app(app, port=1134)
然后我们需要执行 Python 代码以启动服务,为了使 NodeJS 可以执行 Python,我们使用 pyinstaller
将 Python 打包成可执行文件:
# 打包命令
pyinstaller ./py/api.py --clean --distpath ./pydist
# 打包后可执行路径
pydist/api/api
Python 启动了本地 HTTP 服务后,Chromium 和 Node.js 就可以通过请求的方式,与 python 连接通信了:
const res = await axios.default.get('http://localhost:1134/controlMouseAndKeyboard', {
params: {
x,
y,
duration: 0.5,
action: 'move'
}
})
简单来说三个步骤:
- NodeJS 执行 Python代码
- Python 代码启动了一个本地 HTTP 服务
- 通过发起 HTTP 请求与 Python 服务通信
从 Demo 到项目实践的思考
本项目只是一个验证思路的 Demo,真的需要在项目上实践,还需要考虑以下几个点:
应该使用 RPC 通信而不是 HTTP 或者 WebSocket,Demo 使用 HTTP 只是搭建方便。实践中在建立连接、保持连接、异常重连都需要编写更多的逻辑来处理。为什么 Demo 没有使用 zerorpc
? 这个库已经 4 年没有维护了,不兼容新版 NodeJS。
项目通过 pyinstaller
打包成可执行文件来调用 python。实际上其他能编译为可执行文件的语言也一样。还可以使用 WebAssembly
将其他语言编译成 .wasm,在 NodeJS 中引入执行。官方教程:使用 WebAssembly
参考文章
转载自:https://juejin.cn/post/7078268577819656228