1 需求背景

有个需求需要Electron执行在本地执行python脚本。希望通过Electron调用python服务并且实现双向通信。

2 解决思路

使用Electon 的{ exec, spawn, execFile, fork } from "child_process"; 能力来执行python脚本,使用spawn可以实现持续交互,稍后见示例代码。

2.1 在electon打包python和python文件

在开发环境,可以通过直接使用已有python和python文件来测试electron能否执行python。

// 完成代码后后文附上,这里知道在执行python文件就行了
const pythonProcess = spawn(pythonPath, [scriptPath]);

结论:可以执行

2.2 在生产环境测试python执行

在生产环境python包和python文件需要放到resources,打包完成之后,你可以在resources文件夹里面看到python文件夹和你的python文件。
打包配置如下:

"extraResources": [{"from": "python_env.zip","to": "python_env.zip","filter": ["**/*"]},{"from": "electron/main/python","to": "python_scripts","filter": ["**/*.py"]}]

打包后的结果:
在这里插入图片描述

2.3 使用python第三方sdk

在实际应用中肯定不能只用python包,也许使用python sdk。继续调研后得到方法,可以直接使用 python 虚拟环境,python虚拟环境是一个包含你所有三方sdk的独立环境,方便移植。
numpy行测试,输出符合预期。
创建python虚拟环境步骤如下

# 创建虚拟开发环境
`python3 -m venv python_env`# 激活虚拟环境
`source python_env/bin/activate`# 生成 requirement.txt`pip3 freeze > requirements.txt`# 安装依赖`pip3 install -r requirements.txt`

把虚拟环境文件夹python_env打包成zip放到Electron项目里。
注意!!!
需要使用压缩包,在Electron里main直接使用python_env文件夹,可能会打包失败。

2.4 解压缩python虚拟环境,运行python脚本

最近比较忙,到这一步搁置了。以后补上。

示例代码(干货)

ececPy.ts

import { exec, spawn, execFile, fork } from "child_process";
import path from "node:path";
import fs from "fs";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const devPythonPath = path.join(__dirname, "../..");// 查找 Python 可执行文件
function findPython() {console.log("devPythonPath:", devPythonPath);const possibilities1 = [// 在打包的应用中path.join(process.resourcesPath, "python_env", "bin", "python3.9"),];for (const pythonPath of possibilities1) {if (fs.existsSync(pythonPath)) {return pythonPath;}}console.log("Could not find python3 for product, checked", possibilities1);const possibilities2 = [// 在开发环境中path.join(devPythonPath, "python_env", "bin", "python3.9"),];for (const pythonPath of possibilities2) {if (fs.existsSync(pythonPath)) {return pythonPath;}}console.log("Could not find python3 for dev, checked", possibilities2);console.log("测试环境请吧python压缩包解压到项目根目录");const possibilities3 = [// 如果上述路径找不到,尝试系统默认的 python3"python3",];for (const pythonPath of possibilities2) {if (fs.existsSync(pythonPath)) {return pythonPath;}}console.log("Could not find python3 for dev, checked", possibilities3);return null;
}// 启动 Python 进程并进行交互
export async function startPingPong() {console.log("call start pingpong");const pythonPath = findPython();if (!pythonPath) {console.error("Python not found");return;}// 使用 spawn 而不是 execFile 以便进行持续交互// 生产环境路径let scriptPath = path.join(process.resourcesPath,"/python_scripts/pingpong.py");console.log("生产环境 scriptPath:", scriptPath);if (!fs.existsSync(scriptPath)) {scriptPath = "";}// 测试环境路径if (!scriptPath) {scriptPath = path.join(devPythonPath, "/electron/main/python/pingpong.py");console.log("测试环境 scriptPath:", scriptPath);}const pythonProcess = spawn(pythonPath, [scriptPath]);// 处理 Python 输出pythonProcess.stdout.on("data", (data: any) => {try {const response = JSON.parse(data.toString());console.log("Received from Python:", response);// 如果收到 pong,继续发送 pingif (response.action === "pong") {setTimeout(() => {sendPing(pythonProcess, response.count);}, 1000);}} catch (error) {console.error("Error parsing Python response:", error);}});// 处理错误pythonProcess.stderr.on("data", (data: any) => {console.error("Python error:", data.toString());});// 进程退出pythonProcess.on("close", (code: any) => {console.log(`Python process exited with code ${code}`);});// 发送初始 pingsendPing(pythonProcess, 0);
}// 发送 ping 到 Python
function sendPing(process: any, count: any) {const message = {action: "ping",count: count,timestamp: Date.now(),};console.log("Sending to Python:", message);process.stdin.write(JSON.stringify(message) + "\n");
}export const unzipPython = () => {// TODO: 解压python压缩包
};

pingpong.py

import sys
import json
import time
import numpy as np
arr1 = np.array([1, 3, 2, 5, 4])
arr1_str = json.dumps(arr1.tolist())def main():
# 简单的 ping-pong 交互for line in sys.stdin:try:# 解析从 Node.js 发送来的数据data = json.loads(line.strip())if data.get('action') == 'ping':# 收到 ping,回复 pongresponse = {'action': 'pong','timestamp': time.time(),'count': data.get('count', 0) + 1,'arr1_str': arr1_str}print(json.dumps(response))sys.stdout.flush()  # 确保立即发送响应elif data.get('action') == 'exit':# 退出命令breakexcept json.JSONDecodeError:# 处理无效的 JSON 数据error_response = {'error': 'Invalid JSON','received': line.strip()}print(json.dumps(error_response))sys.stdout.flush()if __name__ == '__main__':main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/921202.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/921202.shtml
英文地址,请注明出处:http://en.pswp.cn/news/921202.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode高频 SQL 50 题(基础版)题目记录

Leetcode sql题目记录 文章目录Leetcode sql题目记录570. 至少有5名直接下属的经理1934. 确认率1193. 每月交易I1174. 即时食物配送II176. 第二高的薪水(1) 子查询为空但外层用了聚合函数(2)子查询为空而外层没有聚合函数550. 游戏…

RAGFlow切分方法详解

RAGFlow 各切分方法的含义如下,结合文档结构、场景特点等设计,以适配不同类型的知识源: 1. General(通用分块) 逻辑:结合文本排版、格式、语义关联等因素确定分割点,再根据“建议文本块大小(Token 数)”,将文本切分为合适的块。 支持格式:DOCX、EXCEL、PPT、IMAGE、…

支付域——支付与交易概念

摘要本文详细阐述了支付域中支付与交易的核心概念及其相互关系。交易是商品或服务交换的过程,包含多个要素并产生订单或合同。支付则是资金流转的过程,是交易的资金结算环节。支付交易结合了两者,根据不同场景提供多样化的支付产品和服务。文…

(自用)cmd常用命令自查文档

(自用)cmd常用命令自查文档 Windows CMD 常用命令自查1. 文件与目录操作命令说明示例​cd​显示或切换目录​cd​;cd C:\Windows​​dir​列出目录内容​dir​;dir /a​(含隐藏文件)​md​或mkdir​创建目录​md test​&#xff1…

剧本杀APP系统开发:引领娱乐行业新潮流的科技力量

在当今数字化时代,科技的力量正深刻地改变着人们的生活方式和娱乐习惯。娱乐行业也不例外,各种新兴的娱乐形式和平台如雨后春笋般涌现。剧本杀APP系统开发作为科技与娱乐融合的产物,正以其独特的魅力和创新的模式,引领着娱乐行业的…

LangChain框架深度解析:定位、架构、设计逻辑与优化方向

LangChain框架深度解析:定位、架构、设计逻辑与优化方向 引言 在大语言模型(LLM)应用开发的浪潮中,LangChain作为最具影响力的开发框架之一,为开发者提供了构建复杂AI应用的完整工具链。本文将从框架定位、实现逻辑、设…

面试常备与开发必知:一文掌握MySQL字符串拼接的所有核心技巧

‍ 在 MySQL 中拼接字符串是一个非常常见的操作,主要用于查询时动态组合多个字段或值。以下是几种最核心和常用的方法。一、核心拼接函数1. CONCAT(str1, str2, ...)这是最通用、最常用的字符串拼接函数。它接受两个或多个字符串参数,并将它们按顺…

数据可视化大屏精选开源项目

为您精心挑选和整理了一系列在 GitHub 上广受好评的数据可视化大屏开源项目。这些项目覆盖了不同的技术栈(Vue、React、ECharts、D3.js等),适合从初学者到资深开发者不同层次的需求。 我将它们分为以下几类,方便您选择&#xff1…

LeetCode 3516.找到最近的人:计算绝对值大小

【LetMeFly】3516.找到最近的人:计算绝对值大小 力扣题目链接:https://leetcode.cn/problems/find-closest-person/ 给你三个整数 x、y 和 z,表示数轴上三个人的位置: x 是第 1 个人的位置。y 是第 2 个人的位置。z 是第 3 个人…

【面试】MySQL 面试常见优化问题

1. 为什么要建索引?索引一定能提高性能吗?场景:一个表有上千万数据,查询 SELECT * FROM user WHERE age25;。问题:没有索引时会全表扫描,性能差。解决方案:给 age 建立普通索引,加快…

Access开发导出PDF的N种姿势,你get了吗?

目录 基础篇:一行代码搞定 实战篇:让导出更智能 进阶篇:用户体验升级 总结 hi,大家好呀! 今天我们来聊聊一个非常实用的功能——如何用VBA将Access中的数据导出为PDF。 相信很多朋友在日常工作中都遇到过这样的需…

JavaAI炫技赛:电商系统商品管理模块的创新设计与实践探索

一、引言电商行业的竞争日益激烈,电商系统商品管理模块的高效性、智能化程度成为企业提升竞争力的关键因素。Java 作为企业级开发的主流语言,凭借其稳定性和强大的生态系统,在电商系统开发中占据重要地位。而 AI 技术的融入,为商品…

关于如何在PostgreSQL中调整数据库参数和配置的综合指南

关于如何在PostgreSQL中调整数据库参数和配置的综合指南 PostgreSQL是一个非常通用的数据库系统,能够在低资源环境和与各种其他应用程序共享的环境中高效运行。为了确保它将在许多不同的环境中正常运行,默认配置非常保守,不太适合高性能生产数据库。加上地理空间数据库具有…

wps的excel如何转为谷歌在线表格

1. 打开 Google Sheets(sheets.google.com)。 2. 新建一个空白表格。3. 点击菜单 文件 → 导入 (File → Import)。4. 选择在 WPS 保存好的 .xlsx 文件上传。5. 选择 “新建表格” 或 “替换当前表格”,就能直接在 Google Sheets 使用注…

猫头虎AI 荐研|腾讯开源长篇叙事音频生成模型 AudioStory:统一模型,让 AI 会讲故事

🐯猫头虎荐研|腾讯开源长篇叙事音频生成模型 AudioStory:统一模型,让 AI 会讲故事 大家好,我是猫头虎 🐯🦉,又来给大家推荐新鲜出炉的 AI 开源项目! 这次要聊的是腾讯 A…

收藏!VSCode 开发者工具快捷键大全

一、文件操作快捷键1. 打开与关闭文件Ctrl O(Windows/Linux)或 Command O(Mac):打开文件,可以通过输入文件名快速查找并打开相应文件。Ctrl W(Windows/Linux)或 Command W&#…

Simulations RL 平台学习笔记

1. 选择标准 1.1 开源项目,🌟star数量越多越好 2. 常见平台 2.1 🌟18.6k ML-Agents:基于Unity实现 2.2 🌟1.2k Godot RL Agents

【国内电子数据取证厂商龙信科技】IOS 逆向脱壳

我们都知道,大多数的 APP 在开发的时候一般都会加上一层壳,例如 爱加密、梆梆、360、网易易盾等等。那 APK 的脱壳我们见得多了,那 IOS 逆向脱壳又是怎样子的呢?首先咱们先了解一下为什么要砸壳,因为 IOS 开发者开发软…

基于STM32单片机温湿度PM2.5粉尘甲醛环境质量wifi手机APP监测系统

1 基于STM32单片机温湿度PM2.5粉尘甲醛环境质量WiFi手机APP监测系统 本系统旨在实现对环境中温度、湿度、PM2.5粉尘浓度以及甲醛浓度的实时监测,并通过WiFi技术将数据传输至手机APP端,实现移动化与可视化的环境质量检测。系统在硬件上主要依赖STM32单片…

用C++实现日期类

在上学的时候,总是在计算还有多少天放假;在上班的时候,总是在计算还有多久发工资?我们一般通过日历得到结果,那自己能不能实现一些基本的功能呢?答案是可以的!需要实现内容:1. 日期加…