You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js调用Python子进程返回值未正确获取的解决请求

问题:Node.js调用Python子进程时无法正确获取返回值导致渲染数据undefined

相关代码

getPred.js

const {spawn} = require('child_process');
const path = require('path');
const getPred = () => {
    return new Promise((resolve, reject) => {
        var myjson = {}
        const pythonProcess =  spawn('python3', [
            "-u", 
            path.join( __dirname ,'..', '..', 'scripts', 'run.py'),
            'file'
            ]);

        pythonProcess.stdout.on('data', (data) => {
            mystr = data.toString();
            myjson = JSON.parse(mystr);
            console.log(myjson.predict);
        });
        
        pythonProcess.stderr.on('data', (data) => {
            console.log("fails")
            console.log(`error:${data}`);
            
        });
        pythonProcess.on('close', () => {
            console.log("Closed");
        });
        resolve(myjson);
    });
}
module.exports = {getPred};

main.js

router.post('/predict',  async function (req, res, next) {
  const myjson = await getPred.getPred();
  console.log(myjson);
  console.log("Final", myjson.predict);
  res.render('print.ejs', {
    prods: myjson.predict,
    pageTitle: 'MegNav',
    path: '/',
    hasProducts: 1,
    activeShop: true,
    productCSS: true,
    onPredict: 1 
  });
});

输出结果

Final undefined
1
Closed

问题描述

getPred()函数调用Python脚本获取预测值,但main.js中console.log(myjson)在Python子进程关闭前执行,导致myjson值为undefined。移除async、await和Promise也无法得到正确结果,需要解决该问题,使myjson先获取值再执行页面渲染。

解决方案

问题核心是Promise的resolve时机错误——代码在创建Promise后立刻调用了resolve(myjson),此时Python子进程还没输出数据,myjson还是初始空对象。必须等到子进程执行完成、所有输出数据收集并解析后再resolve,同时完善错误处理逻辑。

修改后的getPred.js

const { spawn } = require('child_process');
const path = require('path');

const getPred = () => {
    return new Promise((resolve, reject) => {
        let stdoutData = '';
        const pythonProcess = spawn('python3', [
            "-u", 
            path.join(__dirname, '..', '..', 'scripts', 'run.py'),
            'file'
        ]);

        // 分段收集Python输出内容
        pythonProcess.stdout.on('data', (data) => {
            stdoutData += data.toString();
        });
        
        // 捕获Python脚本的错误输出
        pythonProcess.stderr.on('data', (data) => {
            console.error(`Python脚本错误: ${data}`);
            reject(new Error(`Python脚本执行失败: ${data}`));
        });

        // 子进程执行完成后解析数据并返回
        pythonProcess.on('close', (code) => {
            console.log("Closed");
            if (code === 0) {
                try {
                    const myjson = JSON.parse(stdoutData);
                    console.log(myjson.predict);
                    resolve(myjson);
                } catch (parseErr) {
                    console.error('JSON解析失败:', parseErr);
                    reject(parseErr);
                }
            } else {
                reject(new Error(`Python脚本异常退出,退出码: ${code}`));
            }
        });

        // 处理子进程启动失败的情况
        pythonProcess.on('error', (err) => {
            console.error('无法启动Python子进程:', err);
            reject(err);
        });
    });
}

module.exports = { getPred };

配套main.js优化(添加错误捕获)

router.post('/predict', async function (req, res, next) {
  try {
    const myjson = await getPred.getPred();
    console.log("Final", myjson.predict);
    res.render('print.ejs', {
      prods: myjson.predict,
      pageTitle: 'MegNav',
      path: '/',
      hasProducts: 1,
      activeShop: true,
      productCSS: true,
      onPredict: 1 
    });
  } catch (err) {
    console.error('获取预测值失败:', err);
    // 返回错误响应,避免请求挂起
    res.status(500).send('获取预测数据失败,请稍后重试');
  }
});

修改要点说明

  • 新增stdoutData变量:Python脚本可能分多次输出数据,拼接后再解析能避免JSON解析失败
  • 调整resolve时机:将resolve移到子进程close事件回调中,确保子进程执行完毕、数据完整后再返回结果
  • 完善错误处理:覆盖子进程启动失败、脚本错误退出、JSON解析失败等场景,通过reject传递错误,便于上层捕获处理
  • main.js添加try-catch:防止因Python脚本出错导致请求长时间挂起,给用户明确的错误反馈

内容的提问来源于stack exchange,提问作者NavinKumarmMNK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 02:30:41