Node.js使用Child Process的Spawn调用Python脚本返回值undefined如何解决
问题原因
python.stdout.on('data')是Node.js的事件监听方法,本身返回的不是Promise对象,await对它无效,不会等待回调执行完成就会继续走后续代码- 你在
data事件回调里写的return,只会把值返回到回调函数本身,根本无法传递给外层的generateCanadaScore函数 - 即使你把
return MexicoData写在函数末尾,也会在Python脚本还没输出数据、data事件还没触发的时候就提前返回初始值,自然拿不到正确结果
解决方案
把整个Python调用过程封装为标准Promise,等Python脚本执行完成、所有输出接收完毕后再返回结果,修改后的代码如下:
const { spawn } = require('child_process'); async function generateCanadaScore(creditscore = 0) { console.log(creditscore, "creditscore"); // 拼接stdout所有输出块,避免大输出时分多次触发data事件丢失数据 let stdoutData = ''; // 收集错误信息 let stderrData = ''; const python = spawn("python", [ "cp_production.py", "sample_dill.pkl", "mexico", Number(creditscore), ]); // 返回Promise,等脚本执行完成后再resolve结果 return new Promise((resolve, reject) => { // 监听stdout数据 python.stdout.on("data", (data) => { console.log("Pipe data from python script ..."); stdoutData += data.toString(); }); // 监听stderr错误 python.stderr.on("data", (data) => { stderrData += data.toString(); }); // 监听脚本执行完成的close事件,此时所有输出都已经接收完毕 python.on("close", (code) => { if (code !== 0) { // 执行异常,返回错误 reject(new Error(`Python脚本执行失败,错误码:${code},错误信息:${stderrData}`)); return; } // 这里可以根据需要trim掉多余的换行/空格 const MexicoData = stdoutData.trim(); console.log(MexicoData); resolve(MexicoData); }); // 监听spawn本身的错误,比如找不到python执行文件 python.on("error", (err) => { reject(new Error(`启动Python进程失败:${err.message}`)); }); }); }
调用代码不需要修改,还是用原来的await调用即可,现在就能正常拿到返回值了。
注意事项
- 如果你的环境里Python3的执行命令是
python3,把spawn的第一个参数改成python3即可 - 如果Python输出有多个字段,可以自行按分隔符切割处理
stdoutData的内容
内容的提问来源于stack exchange,提问作者Vaibhav dadhich
相关产品推荐
相关产品推荐

