I'm trying to run something along the lines of this python script from a javascript file (in an electron
project), and echo the output in real-time:
import time
def main():
print("Hello 1")
time.sleep(1)
print("Hello 2")
time.sleep(1)
print("Hello 3")
return 5
if __name__ == "__main__":
result = main()
print(f"result: {result}")
And I'm using the following Javascript code to execute the file:
// ...
const child = spawn(runners[lang], commandArgs, {shell: true});
child.stdout.setEncoding('utf8');
child.stdout.on('data', (data) => {
console.log(`Received data: ${data}`);
});
What I'm seeing though is all the output being printed out in one giant blob after the whole script finishes running, and not "Hello 1", etc. being sent to my javascript line-by-line. Basically, it seems that my child.stdout.on
callback is only running once. Is there a specific reason for this, and how can I receive data in child.stdout.on
as soon as print
is called in the python script?
To get the expected output, you need to forcibly flush the stdout
stream in your python program. This can be done by adding flush=True
argument.
import time
def main():
print("Hello 1", flush=True)
time.sleep(1)
print("Hello 2", flush=True)
time.sleep(1)
print("Hello 3", flush=True)
return 5
if __name__ == "__main__":
result = main()
print(f"result: {result}", flush=True)
Alternatively you could launch the python interpreter with -u
option. This will force the stdout and stderr streams to be unbuffered. By doing so, you won't have to specify flush=True
on every print
function call.
const { spawn } = require('node:child_process');
const child = spawn("python", ["-u", "your_file_name.py"], {shell: true});
child.stdout.setEncoding('utf8');
child.stdout.on('data', (data) => {
console.log(`Received data: ${data}`);
});