Electron 執行python腳本

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. 日期加…