Node.js python child script output to finish, not realtime

I am new to node.js and socket.io and I am trying to write a small server that will refresh a webpage based on python output.

Eventually this will be used for the temperature sensor, so for now I have a dummy script that prints the temperature values ​​every few seconds:

Thermostat.py

import random, time
for x in range(10):
    print(str(random.randint(23,28))+" C")
    time.sleep(random.uniform(0.4,5))

      

Here's the clipped version of the server:

index.js

var sys   = require('sys'), 
    spawn = require('child_process').spawn, 
    thermostat = spawn('python', ["thermostat.py"]),
    app = require('express')(),
    http = require('http').Server(app),
    io = require('socket.io')(http);

thermostat.stdout.on('data', function (output) { 
    var temp = String(output);
    console.log(temp);
    io.sockets.emit('temp-update', { data: temp});
}); 

app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
    });

      

And finally, the web page:

Index.html

<!doctype html>
<html>
    <head>
        <title>Live temperature</title>
        <link rel="stylesheet" type="text/css" href="styles.css">
    </head>
    <body>
    <div id="liveTemp">Loading...</div>

    <script src="http://code.jquery.com/jquery-1.11.1.js"></script>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        var socket = io();
        socket.on('temp-update', function (msg) {
        $('#liveTemp').html(msg.data)
    });
    </script>

    </body>
</html>

      

The problem is that nodejs seems to get all temperature values ​​at once, and instead of getting 10 temperature values ​​at random intervals, I get all values ​​in one long line after the script finishes:

lots of temp valuesconsole output

+3


source to share


1 answer


You need to turn off output buffering in python. This can be done in a variety of ways, including:

  • Setting environment variable PYTHONUNBUFFERED

  • Passing -u

    to python executable
  • Call sys.stdout.flush()

    after every entry (or print()

    in your case) to stdout
  • For Python 3.3+, you can pass flush=true

    to print()

    :print('Hello World!', flush=True)



Also, in your node code (even if you have a dream in python code and now you erase stdout), you really shouldn't assume that there will always be only one line output

in your data handler for thermostat.stdout

.

+6


source







All Articles