跨语言集成:将 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脚本的能力啦。

相关推荐
nyf_unknown1 分钟前
(css)element中el-select下拉框整体样式修改
前端·css
数据小爬虫@10 分钟前
Python爬虫:如何优雅地“偷窥”商品详情
开发语言·爬虫·python
m0_5485147711 分钟前
前端打印功能(vue +springboot)
前端·vue.js·spring boot
闰土_RUNTU15 分钟前
Pytorch分布式训练print()使用技巧
人工智能·pytorch·python·分布式训练·训练技巧
执键行天涯18 分钟前
element-plus中的resetFields()方法
前端·javascript·vue.js
Days205023 分钟前
uniapp小程序增加加载功能
开发语言·前端·javascript
喵喵酱仔__24 分钟前
vue 给div增加title属性
前端·javascript·vue.js
dazhong201233 分钟前
HTML前端开发-- Iconfont 矢量图库使用简介
前端·html·svg·矢量图·iconfont
零光速37 分钟前
数据处理与统计分析——10-Pandas可视化-Matplotlib的常用API
数据结构·python·数据分析·pandas·matplotlib
m0_748248771 小时前
前端vue使用onlyoffice控件实现word在线编辑、预览(仅列出前端部分需要做的工作,不包含后端部分)
前端·vue.js·word