1

I'm writing a simple web app to get a handle on how node child processes work. Basically you enter your name into an angular frontend which passes the name to an express backend in a javascript object. The backend passes the name as an argument to a simple python script as a command line argument using the child_process module. Theres nothing wrong with the front end and the name gets successfully passed to the backend but when I call stdout on the python process it doesn't work. There aren't any error messages.

Heres the express code:

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});
  });
});

I put two console.log statements in the code to debug it. The first one prints the data but the second one inside the stdout function isn't called at all. The python script is in the same folder as the app.js express file so I'm pretty sure theres nothing wrong with the file path.

Here's the python script:

import sys

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

When I run it in the command line it works exactly as expected but I included it anyway just in case.

1
  • 1
    There's a great repository which already implements interfacing between node.js and python. In a very similar to your way. Maybe it will serve as a solution and source of inspiration for your purposes: github.com/extrabacon/python-shell Commented Apr 13, 2021 at 19:51

3 Answers 3

0

Process.stdout.on will keep on streaming until the end event. The code is wrong because you are actually sending response for every time there is some value in stdout. And you cant set the response header more than once. Try writing the code in below way. Thanks

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

Process.on("end", () => {
     // send response here
});
Sign up to request clarification or add additional context in comments.

3 Comments

I actually tried that and it's still not working. I tried doing the same thing without using express and it worked fine. When I try to output the data with a console.log() statement nothing happens. I don't even get an error. I've been trying every variation in syntax I can think of and I keep getting the same result. I honestly have no idea whats going on. If you or anyone else can think of anything I'd really appreciate it.
have you tried setting python environment variable PYTHONUNBUFFERED=TRUE ?
I tried this but the output is not json format... it's a string and it containts special characters like these '\r','\n'... and if i don't convert to string I get this type ofutput.. { "type": "Buffer", "data": [ 79, 117, 116, 112, 117, 116 ..... and so on numbers ] }. Can you tell me how to send json output from res.send()?
0

close will trigger when your data completes

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"]);
}
});

3 Comments

You should explain your solution -- what do different parts do, how is it different from the code OP provided, why doesn't their code work and yours does?
when we try to send response in stdout.on('data') the child process isnot completed they provide method close where after completeion we send all child process data in respnse
What I meant is that this comment with a bit more detail should accompany your answer. you can edit your answer.
0

Instead of

console.log(data)

use

console.log(data.toString())

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.