Thursday 27 August 2020

Live Python Output to Node.js Parent Process

Hi everyone,I'm trying to send the live output of a child Python process, launched in Node.js, to the parent process. I've tried piping the child's output, but receive errors (see below), or inheriting the child's stdio to parent. In either case, I send the terminal output with socket.io.I'm able to spawn a Python process successfully, and the Python's script output is sent live (have tried synchronous and asynchronous varieties) to Node's console. However, I'm unable to display this on a web page (I'm using Socket.io for the server-client communication), without the web page being nothing but raw text (res.send).The two examples below refer to the same python script launched and the same webpage hosted on a node server (using Express).Example 1:app.post('/webpageoutput', function(req,res) { var io = require('socket.io')(http); var child = require('child_process'); var events = require('events'); var eventEmitter = new events.EventEmitter(); eventEmitter.on('logging', function(message) { io.emit('log_message', message); }); io.on('connection', function(socket) { console.log('Continuing node activities while process spawns'); var python_process = child.spawn( 'python3', ['pythonscript.py'], {stdio: 'pipe'}); python_process.stdout.on('data', function (data) { process.stdout.write(data.toString()); }); python_process.stderr.on('data', function (data) { process.stdout.write(data.toString()); python_process.on('close', function (code) { console.log("Process finished " + code); }); }) }); // Emit console.log var existingconsoleLog = console.log; console.log = function(python_process) { eventEmitter.emit('logging', python_process); existingConsoleLog(python_process); }; res.render('webpageoutput'); }); As expected, using "stdio: 'inherit", throws a "TypeError: Cannot read property 'on' of null" (for stdout) and using "stdio: 'pipe' " prevents the child Python process from starting at all. I've also tried both, as well as exec, execSync, and spawnSycn (although I require asynchronous launching of processes as both parent and child must run in parallel) but piping the child's output to the parent is as far as I've gotten.Example 2:io.on('connection', function(socket){ console.log('Continuing node activities while process spawns'); var python_process = child.spawn( 'python3', ['pythonscript.py'], {stdio: 'pipe'}); var chunk = ''; python_process.stdout.on('data', function(data) { chunk += data socket.emit('newdata', chunk); }); python_process.stderr.on('data', function (data) { console.log('Failed to start child process.'); }) }) // Emit console.log (same as above, console.log & render; skipped to save space) 2 Questions (Only need 1 solution)Is there anyway to send new messages/terminal output using socket.io from the parent process using {stdio: 'inherit'}? I understand that STDOUT and STDERR can't be used with 'pipe', and I've launched python processes using 'inherit', but although its the parent process which receives the output I can't display this to the webpage.Why does "Example 1" fail to launch the process completely?

Submitted August 28, 2020 at 01:11AM by empathyman-1234

No comments:

Post a Comment