【问题标题】:Nodejs child process wont return data from python script to stdoutNodejs子进程不会将数据从python脚本返回到stdout
【发布时间】:2019-11-09 21:08:25
【问题描述】:

我正在编写一个简单的网络应用程序来了解节点子进程的工作方式。基本上,您将您的姓名输入到一个角度前端,该前端将名称传递给 javascript 对象中的一个快速后端。后端使用 child_process 模块将名称作为参数传递给简单的 python 脚本作为命令行参数。前端没有问题,名称成功传递到后端,但是当我在 python 进程上调用 stdout 时,它不起作用。没有任何错误消息。

这里是快递代码:

app.post('/api', (req, res, next) => {
  console.log(req.body.name);

  const spawn = require('child_process').spawn;

  const process = spawn('python3', ['./hello.py', req.body.name]);

  process.stdout.on('data', (data) => {
    console.log(data);
    res.status(200).json({greeting: data});
  });
});

我在代码中放了两条 console.log 语句来调试它。第一个打印数据,但 stdout 函数中的第二个根本不调用。 python脚本与app.js express文件在同一个文件夹中,所以我很确定文件路径没有问题。

这是python脚本:

import sys

print('hello' + sys.argv[1])
sys.stdout.flush()

当我在命令行中运行它时,它的工作方式完全符合预期,但为了以防万一,我还是包含了它。

【问题讨论】:

  • 有一个很棒的存储库已经实现了 node.js 和 python 之间的接口。与您的方式非常相似。也许它会为您的目的提供解决方案和灵感来源:github.com/extrabacon/python-shell

标签: python node.js express


【解决方案1】:

Process.stdout.on 将继续流式传输直到结束事件。该代码是错误的,因为您实际上是在每次标准输出中有某些值时发送响应。而且您不能多次设置响应标头。尝试按以下方式编写代码。谢谢

 let output;
Process.stdout.on("data", (data) => {
      output += data;
});

Process.on("end", () => {
     // send response here
});

【讨论】:

  • 我确实试过了,但还是不行。我尝试在不使用 express 的情况下做同样的事情,并且效果很好。当我尝试使用 console.log() 语句输出数据时,没有任何反应。我什至没有收到错误。我一直在尝试所有我能想到的语法变化,并且一直得到相同的结果。老实说,我不知道发生了什么。如果您或其他人能想到任何事情,我将不胜感激。
  • 你试过设置python环境变量PYTHONUNBUFFERED=TRUE吗?
  • 我试过了,但输出不是 json 格式...它是一个字符串,它包含特殊字符,例如 '\r'、'\n'... 如果我不转换到字符串我得到这种类型的输出.. { "type": "Buffer", "data": [ 79, 117, 116, 112, 117, 116 ..... 等等数字] }。你能告诉我如何从 res.send() 发送 json 输出吗?
【解决方案2】:

当您的数据完成时会触发关闭

app.get("/list-account", async (req, res) => {
try {
let array = "";
let response = await child.spawn(
path.join(__dirname, "xcv-alpha-keychain.exe"),
["listaccounts"]
);
await response.stdout.on("data", (data) => {
const stdout = data.toString();
console.log("stdout", stdout);
array += stdout;
// return res.status(200).json({ array });
});
response.stderr.on("data", (data) => {
return res.status(500).send(data.toString());
});
response.on("error", (error) => {
return res.status(500).send({ error });
});
response.on("close", (code) => {
return res.status(200).json({ array, code });
});

} catch (error) {
return res.status(500).send(["a", "b", "c"]);
}
});

【讨论】:

  • 你应该解释你的解决方案——不同的部分有什么作用,它与 OP 提供的代码有什么不同,为什么他们的代码不起作用而你的代码起作用?
  • 当我们尝试在 stdout.on('data') 中发送响应时,子进程未完成,他们提供关闭方法,完成后我们在响应中发送所有子进程数据
  • 我的意思是,这个更详细的评论应该伴随你的回答。你可以编辑你的答案。
猜你喜欢
  • 1970-01-01
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
相关资源
最近更新 更多