0

I've got a node.js application that needs to pass input to a python program and get the input back. This process needs to occur frequently and with as little latency as possible. Thus I've chosen to use the child_process package. The javascript code is below

child_process = require('child_process');

class RFModel {

    constructor () {

        this.answer = null;
        this.python = child_process.spawn('python3', ['random_forest_model.py']);

        this.python.stdout.on('data', (data)=>{
            this.receive(data);
        });
        
    }

    send (data) {
        this.answer = null;
        this.python.stdin.write(data);
    }

    receive (data) {
        data = data.toString('utf8')
        console.log(data)
        this.answer = data;
    }

}

const model = new RFModel()

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
(async ()=>{
    await timeout(7000)
    model.send('asdf')
})();

And this is the python code:

import sys

sys.stdout.write('test')
sys.stdout.flush()

for line in sys.stdin:
    open("test.txt", "a") #janky test if input recieved

    sys.stdout.write(line)
    sys.stdout.flush()

The nodejs process receives the first "test" output from the python process, but it does not seem like python is receiving any input from nodejs, since there is no echo or text file being created. What am I doing wrong?

Ryan Keathley
  • 49
  • 1
  • 5

1 Answers1

2

I'm not a python expert, but presumably, for line in sys.stdin: is expecting an actual line (a series of characters followed by a line break character). But, from your nodejs program you aren't sending a line break character. You're just sending a series of characters. So your Python program is still waiting for the line break character to signify the end of the line.

Try changing this:

model.send('asdf')

to this:

model.send('asdf\n')

When I run it now with this change, I get this output:

test
asdf

Where there's a delay before the asdf shows up.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Good observation, but it doesn't fix. It allows the python subprocess to terminate, however. This also causes the node process to terminate unless I add, say, a longer timeout. The node process does not print "test" and no txt file either. EDIT: My mistake, I had sys.stdin.buffer instead of just sys.stdin. With the latter, it seems to work just as described in the OP – Ryan Keathley Mar 27 '22 at 06:14
  • @RyanKeathley - When I run this code, I get `test` and then `asdf` in the console. I don't know what the point of `open("test.txt", "a")` is in your program as it doesn't seem to have anything to do with anything. It doesn't affect `stdin` or `stdout` (which is all you're interacting with) and you don't capture the filehandle that `open()` returns so that isn't doing anything. – jfriend00 Mar 27 '22 at 06:17
  • @RyanKeathley - My nodejs process does not terminate by itself. I have to ^C it to get it to stop. It displays `test`, then `asdf\n`, then waits forever. So, as of now, I get the output that is expected and don't understand what question you still have about this? If you're still confused about something, please explain what you are still confused about. – jfriend00 Mar 27 '22 at 06:25
  • It's commented that it's just a test. Reason being that python might be received in the 'asdf' but is not node is not getting the echo. OMG you are correct I also had the flush command removed from the for loop. – Ryan Keathley Mar 27 '22 at 06:27