node项目中调用执行python脚本的方法详解

 更新时间:2026年03月05日 08:35:32   作者:允许部分打工人先富起来  
这篇文章主要为大家详细介绍了node项目中调用执行python脚本的两个常用方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

一、环境配置

Windows + PowerShell 命令:

  • 在node项目中新建python文件夹,以及子文件夹scripts用于放置python脚本
  • 创建虚拟环境 cd python -> python -m venv venv
  • 进入虚拟环境并install脚本中的依赖:venv\Scripts\Activate.ps1 -> 单个安装 pip install pandas
  • 不要把 venv 提交到 git
// .gitignore
python/venv/
__pycache__/
*.pyc

只提交依赖清单

执行:pip freeze > requirements.txt 提交这个文件即可

服务器部署时重新创建环境

  • python -m venv venv
  • pip install -r requirements.txt

二、运行python脚本

方法一:用spawn 子进程通信(不建议)

缺点:频繁 spawn 会很慢,stdout 容易污染

注意:

  • 绝对路径的拼接,以及脚本里如果有读取文件代码时的文件路径
  • Python脚本里不能随便 print,因为node必须自己保证输出是 JSON
const { spawn } = require("child_process");
const path = require("path");
const rootPath = path.resolve(__dirname, "..");
// 1️⃣ 定位 Python 解释器路径:E:\node\xxx\python\venv\Scripts\python.exe
const pythonPath = path.join(
  rootPath,
  "python",
  "venv",
  "Scripts",
  "python.exe",
);
// 2️⃣ 定位 Python 脚本路径:E:\node\xxx\python\scripts\test.py
const scriptPath = path.join(
  rootPath,
  "python",
  "scripts",
  "test.py",
);
// 🔐 全局执行锁
let isRunning = false;

// 注意脚本文件里访问文件时的路径,要用绝对路径
exports.get_info = (req, res) => {
  if (isRunning) {
    return res.send({
      status: 429,
      message: "任务正在执行中,请稍后再试",
    });
  }

  isRunning = true;

  // 第二个参数是数组,表示执行哪个脚本,和传给 Python 的参数
  const py = spawn(pythonPath, [scriptPath]);

  let error = "";

  py.stderr.on("data", (data) => {
    error += data.toString();
  });

  py.on("error", (err) => {
    console.error("启动失败:", err);
    isRunning = false;
    return res.send({
      status: 500,
      message: "Python 启动失败",
      error: err.message,
    });
  });
  // 超时杀进程
  const timeout = setTimeout(() => {
    py.kill("SIGTERM");
  }, 300000); // 300秒超时

  py.on("close", (code) => {
    clearTimeout(timeout);
    isRunning = false;
    if (code === 0) {
      return res.send({
        status: 200,
        message: "Python脚本执行成功",
      });
    }

    console.error("Python执行错误:", error);

    return res.send({
      status: 500,
      message: "Python执行失败",
      error: error || "未知错误",
    });
  });
};

每个请求都 spawn 一个 Python 进程,如果接口被并发打(比如前端连点多次请求、或者有压测),就会同时起多个 python.exe 导致内存瞬间爆掉,所以这里限制了单进程:

①在脚本test.py里强制限制线程,放在所有import之前

import os
os.environ["OPENBLAS_NUM_THREADS"] = "1"
os.environ["OMP_NUM_THREADS"] = "1"
os.environ["MKL_NUM_THREADS"] = "1"

②加单进程锁(不允许并发执行),以及加超时杀进程(防卡死)

同一时间只执行一个 Python 脚本,后面的请求直接拒绝,在“单进程 + spawn 模式”下,只要 Python 进程正常退出,内存会被系统回收。

方法二:使用FastAPI(推荐)

用 Python 起一个 API 服务,Node 通过 HTTP 调用,稳定性最高,避免:spawn 死锁、buffer 溢出、JSON污染

Step1:进入虚拟环境安装 FastAPI 和 uvicorn

cd python 
venv\Scripts\Activate.ps1
pip install fastapi "uvicorn[standard]"

Step2:Python 起 API 服务,新建入口文件 api_server.py

# api_server.py 
import os
from fastapi import FastAPI
import sys

# 关键:让 python 能识别 scripts 目录
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(BASE_DIR)
# 从 scripts 引入
from scripts.test import get_test_info   

app = FastAPI()
# 注册路由:
@app.get("/aaa/bbb")
async def ccc():
    result = await get_test_info()
    return result

Step3:把脚本文件改成接口驱动模式的函数写法

比如异步任务时 if __name__ == "__main__": 改成async 函数 async def get_test_info(): 并return json:

return {
    "status": 200,
    "file": result_file
}

注意:FastAPI 本身已经运行在事件循环里,不能在脚本文件里 asyncio.run()

Step4:在不同端口启动这个 FastAPI 应用实例:uvicorn api_server:app --host 0.0.0.0 --port 8000 --reload

Step5:不再 spawn,改成 axios 请求:

const axios = require("axios");
// 全局执行锁
let isRunning = false;

// 注意脚本文件里访问文件时的路径,要用绝对路径
exports.get_info = async (req, res) => {
  if (isRunning) {
    return res.send({
      status: 429,
      message: "任务正在执行中,请稍后再试",
    });
  }

  isRunning = true;

  try {
    const response = await axios.get(
      "http://127.0.0.1:8000/aaa/bbb",
      {
        timeout: 300000, // 5分钟超时
      }
    );

    isRunning = false;
    
    return res.send({
      status: 200,
      message: "Python脚本执行成功",
      data: response.data,
    });
  } catch (error) {
    isRunning = false;

    return res.send({
      status: 500,
      message: "FastAPI调用失败",
      error: error.message,
    });
  }
};

到此这篇关于node项目中调用执行python脚本的方法详解的文章就介绍到这了,更多相关node调用python脚本内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Node.js模板引擎教程-jade速学与实战1

    基于Node.js模板引擎教程-jade速学与实战1

    下面小编就为大家带来一篇基于Node.js模板引擎教程-jade速学与实战1。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • Nest.js环境变量配置与序列化详解

    Nest.js环境变量配置与序列化详解

    这篇文章主要给大家介绍了关于Nest.js环境变量配置与序列化的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Node.js基于cors解决接口跨域的问题(推荐)

    Node.js基于cors解决接口跨域的问题(推荐)

    这篇文章主要介绍了Node.js基于cors解决接口跨域的问题,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • npm全局环境变量配置详解

    npm全局环境变量配置详解

    这篇文章主要介绍了npm全局环境变量配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • Nodejs进阶:基于express+multer的文件上传实例

    Nodejs进阶:基于express+multer的文件上传实例

    本篇文章主要介绍了基于express+multer的文件上传实例,现在分享给大家,也给大家做个参考,感兴趣的小伙伴们可以参考一下。
    2016-11-11
  • Nodejs中JSON和YAML互相转换方式

    Nodejs中JSON和YAML互相转换方式

    这篇文章主要介绍了Nodejs中JSON和YAML互相转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • node 文件上传接口的转发的实现

    node 文件上传接口的转发的实现

    这篇文章主要介绍了node 文件上传接口的转发的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • 图解NodeJS实现登录注册功能

    图解NodeJS实现登录注册功能

    这篇文章主要介绍了NodeJS实现登录注册功能,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • 三行命令切换Node.js版本的流程步骤

    三行命令切换Node.js版本的流程步骤

    如何在Windows上更新Node.js版本呢?有没有那种不需要重新安装软件再修改配置文件和环境变量的方法?你是否还在为可能要重新安装Node然后配置文件修改环境变量困扰?面就来介绍一下nvm更换node版本的步骤,需要的朋友可以参考下
    2024-01-01
  • Node.js创建Web、TCP服务器

    Node.js创建Web、TCP服务器

    这篇文章主要介绍了用Node.js创建Web服务器和TCP服务器的方法和处理技巧,需要的读者们学习一下吧。
    2017-12-12

最新评论