Node.js调用Python脚本时函数无法返回JSON 如何用async-await解决
问题解决方法
核心原因
child_process.spawn 是基于回调事件的异步API,你之前的写法没有等待Python进程执行完成、输出返回就直接返回了变量,所以拿到的是未赋值的undefined。你后续改造的代码中直接await普通变量dataToSend没有任何等待效果,async/await仅能等待Promise对象的状态变更,必须先将回调逻辑包装为Promise才能实现等待效果。
正确改造代码
const { spawn } = require('child_process') const path = require('path') // 用于跨平台拼接路径,避免windows/linux路径分隔符差异报错 const getWeatherReport = (location) => { // 整个逻辑包装为Promise返回 return new Promise((resolve, reject) => { let output = '' // 用于拼接所有stdout输出,避免大数据分包导致JSON解析失败 // 用path.join拼接路径,兼容多系统 const python = spawn('python', [path.join(__dirname, 'weathergetter.py'), location.toString()]) // 收集stdout输出 python.stdout.on('data', (data) => { console.log('接收Python脚本输出数据...') output += data.toString() }) // 捕获错误输出 python.stderr.on('data', data => { console.error(`Python脚本错误输出: ${data}`) reject(new Error(data.toString())) }) // 捕获进程执行错误 python.on('error', (err) => { console.error('启动Python进程失败:', err) reject(err) }) // 进程关闭时处理最终结果 python.on('close', (code) => { console.log(`Python进程退出,退出码: ${code}`) if (code === 0) { try { // 所有输出收集完成后再解析JSON const dataToSend = JSON.parse(output.replace(/\'/g, '\"')) resolve(dataToSend) } catch (parseErr) { reject(new Error(`JSON解析失败: ${parseErr.message}, 原始输出: ${output}`)) } } else { reject(new Error(`Python进程异常退出,退出码: ${code}`)) } }) }) } // 调用方式 // 如果你是在Node.js 14.8+版本,可以直接用顶层await const wea = await getWeatherReport("kolkata") console.log('天气数据:', wea) // 如果是低版本Node.js不支持顶层await,用async自执行函数包裹 // ;(async () => { // const wea = await getWeatherReport("kolkata") // console.log('天气数据:', wea) // })()
代码优化点说明
- 用
path.join拼接文件路径,避免Windows和Linux系统路径分隔符不同导致的脚本找不到错误 - 新增stdout输出拼接逻辑,避免Python输出内容过长被Node.js分包传输时,只拿到部分内容导致JSON解析失败
- 新增完整的错误捕获逻辑,脚本执行错误、进程启动失败、JSON解析错误都可以被上层通过
try/catch捕获 - 仅在进程正常退出且所有输出接收完成后才解析JSON并返回结果,保证返回的数据完整性
内容的提问来源于stack exchange,提问作者Curious Learner
相关产品推荐
相关产品推荐

