激光

wei_lai 8c50232fad 激光测量v2.2,添加测试版注释,删除正式版注释,修改部分数据格式 6 bulan lalu
api_test.py fd93310e63 激光测量v2,增加了分析数据本地保存,实时调取,分析历史管理 6 bulan lalu
data_analyse_origin.py 8c50232fad 激光测量v2.2,添加测试版注释,删除正式版注释,修改部分数据格式 6 bulan lalu
data_clean.py 8c50232fad 激光测量v2.2,添加测试版注释,删除正式版注释,修改部分数据格式 6 bulan lalu
frequency_filter.py 57b5a9357d 激光测量v2.1,修复了坐标归一化的计算错误问题,添加测试版注释,删除正式版注释 6 bulan lalu
orginal_plot.py 0d551f5eb7 激光测量v1 6 bulan lalu
readme1.md 0d551f5eb7 激光测量v1 6 bulan lalu
test.py 0d551f5eb7 激光测量v1 6 bulan lalu

readme1.md

🎯 目标:用 Python 作为 EXE,暴露 /api/a1 和 /api/a2 两个 API

思路:Electron 通过 child_process.execFile 运行 Python EXE,Python 解析 API 名称和参数,执行相应逻辑并返回 JSON 结果。


🔹 1️⃣ Python 代码

创建 data_analyse.py,用于处理 API 请求。

import sys
import json

# **定义 API 处理函数**
def api_a1():
    return {"message": "Hello from API A1"}

def api_a2(data):
    return {"received": data}

if __name__ == "__main__":
    # **🔹 解析命令行参数**
    if len(sys.argv) < 2:
        print(json.dumps({"error": "No API specified"}))
        sys.exit(1)

    api_name = sys.argv[1]  # 第一个参数是 API 名称

    if api_name == "a1":
        result = api_a1()
    elif api_name == "a2":
        if len(sys.argv) < 3:
            print(json.dumps({"error": "No data for A2"}))
            sys.exit(1)
        data = json.loads(sys.argv[2])  # 解析 JSON 参数
        result = api_a2(data)
    else:
        result = {"error": "Unknown API"}

    print(json.dumps(result))  # **返回 JSON 格式数据**

🔹 2️⃣ 将 Python 代码打包成 EXE

📌 安装 pyinstaller

pip install pyinstaller

📌 生成 EXE

pyinstaller --onefile data_analyse.py

成功后,你会在 dist/ 目录下找到 data_analyse.exe

📌 复制 EXE 文件到 Electron 项目dist/data_analyse.exe 复制到 ../severs/dist/data_analyse/


🔹 3️⃣ Electron 主进程调用 Python EXE

修改 main.mjs,让 Electron 监听渲染进程的请求 并运行 Python EXE。

import { app, BrowserWindow, ipcMain } from "electron";
import { fileURLToPath } from "url";
import path from "path";
import { execFile } from "child_process";

process.env["ELECTRON_DISABLE_SECURITY_WARNINGS"] = "true";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

let mainWindow = null;

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1000,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, "./preload.mjs"),
      contextIsolation: true,
      nodeIntegration: false,
      allowRunningInsecureContent: false,
    },
  });

  if (process.env.NODE_ENV === "development") {
    mainWindow.loadURL("http://localhost:5173/home");
    mainWindow.webContents.openDevTools();
  } else {
    mainWindow.loadFile(path.join(__dirname, "../dist/index.html"));
    mainWindow.webContents.openDevTools();
  }

  mainWindow.on("closed", () => {
    mainWindow = null;
  });
}

// **🔹 监听渲染进程的请求,执行 Python EXE**
ipcMain.handle("run-python-exe", async (event, apiName, params = {}) => {
  return new Promise((resolve, reject) => {
    const pythonExePath = path.join(
      __dirname,
      "../severs/dist/data_analyse/data_analyse.exe"
    ); // **Python EXE 路径**

    // **传递 API 名称和参数**
    const args = [apiName, JSON.stringify(params)];

    const child = execFile(pythonExePath, args, (error, stdout, stderr) => {
      if (error) {
        console.error("❌ Python EXE 运行失败:", error);
        reject(`Error: ${error.message}`);
        return;
      }
      if (stderr) {
        console.warn("⚠️ Python EXE 输出警告:", stderr);
      }

      try {
        resolve(JSON.parse(stdout)); // **解析 JSON 返回给前端**
      } catch (parseError) {
        reject("Invalid JSON response from Python");
      }
    });
  });
});

app.whenReady().then(createWindow);

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") app.quit();
});

app.on("activate", () => {
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
});

export { createWindow };

🔹 4️⃣ 渲染进程(前端)调用 Python

修改 preload.mjs,暴露 API 让前端调用。

import { contextBridge, ipcRenderer } from "electron";

contextBridge.exposeInMainWorld("electronAPI", {
  callPythonAPI: (apiName, params) =>
    ipcRenderer.invoke("run-python-exe", apiName, params),
});

🔹 5️⃣ 前端(Vue / React / HTML)调用 Python

async function fetchA1() {
  try {
    const result = await window.electronAPI.callPythonAPI("a1");
    console.log("A1 API 响应:", result);
  } catch (error) {
    console.error("A1 API 失败:", error);
  }
}

async function fetchA2() {
  try {
    const result = await window.electronAPI.callPythonAPI("a2", {
      name: "Alice",
    });
    console.log("A2 API 响应:", result);
  } catch (error) {
    console.error("A2 API 失败:", error);
  }
}

fetchA1();
fetchA2();

✅ 运行步骤

1️⃣ 先编译 Python 为 EXE

pyinstaller --onefile data_analyse.py

然后把 dist/data_analyse.exe 复制到 ../severs/dist/data_analyse/


2️⃣ 运行 Electron

npm run electron:dev

🚀 运行结果

  • 调用 callPythonAPI("a1")

    { "message": "Hello from API A1" }
    
    • 调用 callPythonAPI("a2", { "name": "Alice" }) json { "received": { "name": "Alice" } }

🎯 总结

  1. Python 解析 API 名称和参数,执行相应逻辑,并返回 JSON 结果。
  2. Electron 主进程监听前端的调用,用 execFile 运行 Python EXE,并传递 API 名称和参数。
  3. 渲染进程(前端)使用 window.electronAPI.callPythonAPI() 触发 Python 调用。
  4. Electron 解析 Python 输出,并返回给前端

这样你就成功在 Electron 中调用 Python EXE,并通过 JSON 格式返回 API 数据! 🚀🚀🚀