跨语言集成:将 Python 的强大功能带入 Nodejs 应用

背景

最近在electrion项目中,我需要使用一个特定的 Python 库功能,希望使用 JavaScript 调用Python方法并得到运行结果。

技术调研

Node与Python通信

前提:你的操作系统上已安装python3。

Node.js 的child_process模块允许你创建子进程来执行系统命令,包括运行 Python 脚本。child_process模块提供了两个常用命令execspawn

exec适用于执行短命令并在命令完成后获取完整的输出。它将子进程的输出缓存在内存中,适合处理小数据量。

spawn适用于处理流式数据。这意味着如果你需要处理大数据量的输出,比如从子进程持续接收数据并进行处理,spawn更加合适。

示例代码:

javascript 复制代码
// Nodejs代码
const { exec } = require('child_process');

const command = 'python3 example.py chenchen501';

exec(command, (error, stdout, stderr) => {
    if (error) {
        console.error(`执行错误: ${error}`);
        return;
    }
    console.log(`输出: ${stdout}`); // 此处输出结果 Hello, chenchen501
    if (stderr) {
        console.error(`错误: ${stderr}`);
    }
});

// example.py代码
import sys
def main():
    if len(sys.argv) > 1:
        name = sys.argv[1]
        print(f"Hello, {name}!")
    else:
        print("Hello, World!")

if __name__ == "__main__":
    main()

当然如果你有大量数据从python脚本中返回,需要使用spawn,否则会因为内存溢出导致异常。

javascript 复制代码
const { spawn } = require('child_process');
// 调用 Python 脚本
const pythonProcess = spawn("python3", ["example.py", "chenchen501"]);
// 处理输出
pythonProcess.stdout.on('data', (data) => {
    console.log(`Output: ${data}`);
});
// 处理错误
pythonProcess.stderr.on('data', (data) => {
    console.error(`Error: ${data}`);
});
// 处理进程结束
pythonProcess.on('close', (code) => {
    console.log(`Python process exited with code ${code}`);
});

还是spawn命令适用范围更广,但是写上还是用的会调,更加简洁的写法是类似Promise的链式调用写法,为了达此目的使用tinyspawn库:

ini 复制代码
npm install tinyspawn

const tinyspawn = require('tinyspawn');
 
const command = 'python3';
const args =["example.py", "chenchen501"];

// 使用 tinyspawn 执行命令
tinyspawn(command, args)
    .then(result => {
        console.log(`输出: ${result.stdout}`);
        if (result.stderr) {
            console.error(`错误: ${result.stderr}`);
        }
    })
    .catch(error => {
        console.error(`执行错误: ${error}`);
    });

支持多平台

由于在macOS上的命令是python3,但是在windows上是python。所以代码中要识别系统环境并调用不同的命令。

javascript 复制代码
const tinyspawn = require("tinyspawn");
const path = require("path");

function getPythonCommand() {
  // 检测操作系统
  const isMac = process.platform === "darwin";
  const isWindows = process.platform === "win32";

  let result = "python3";
  if (isMac) {
    result = "python3";
  } else if (isWindows) {
    result = "python";
  } else {
    // 对于其他类 Unix 系统(如 Linux),通常也使用 python3
    result = "python3";
  }
  return result;
}

function getPythonScript() {
  return path.join(__dirname, "example.py");
}

// 使用 tinyspawn 执行命令
tinyspawn(getPythonCommand(), [getPythonScript(), "chenchen501"])
  .then((result) => {
    console.log(`输出: ${result.stdout}`);
    if (result.stderr) {
      console.error(`错误: ${result.stderr}`);
    }
  })
  .catch((error) => {
    console.error(`执行错误: ${error}`);
  });

增加python环境判断

因为我们的nodejs程序需要有python环境才能调用python脚本,所以最好加上环境判断逻辑,这里推荐一个小库binary-version-check, 轻松判断命令的版本。

javascript 复制代码
import binaryVersionCheck from 'binary-version-check';

try {
	await binaryVersionCheck('python3', '>=3.7');
} catch (error) {
	console.log(error);
	//=> 'InvalidBinaryVersion: curl 7.30.0 doesn't satisfy the version requirement of >=8'
}

支持无python环境

如果制作如electron客户端应用。需要安装到用户电脑上,可以考虑将python脚本连通python一起打包成二进制可执行程序,这样可以无需安装python也可以利用python的能力。

总结

如上,我们学会了在nodejs中使用python,为了提供给其他前端同学使用,我们同样可以将调用python的逻辑封装到npm包中,这样可以让其他同学无感知的使用python脚本的能力啦。

相关推荐
kyriewen10 小时前
Anthropic 估值逼近万亿美元,Claude Sonnet 5 + Claude Science 一天两连发
前端·ai编程·claude
小徐_233312 小时前
Wot UI 2.2.0 发布:Button 新增 subtle,VideoPreview 预览体验继续增强
前端·微信小程序·uni-app
天蓝色的鱼鱼14 小时前
关于 CSS 你可能不知道的属性,但关键时刻很有用
前端·css
SelectDB14 小时前
Apache Doris Python UDF:让 SQL 直接调用 Python 生态,支撑 Agent 时代复杂业务逻辑
大数据·数据库·python
泯泷15 小时前
第 2 篇:设计第一套字节码:Opcode、Instruction 与 Constant Pool
前端·javascript·安全
妙码生花15 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
泯泷15 小时前
第 1 篇:从 1 + 2 开始:亲手写出第一台 JSVM
前端·javascript·安全
团团崽_七分甜15 小时前
Spring Boot 核心知识点总结
前端
lichenyang45315 小时前
从一个按钮开始,理解 ASCF 框架到底在做什么
前端