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:
source to share
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 (orprint()
in your case) to stdout - For Python 3.3+, you can pass
flush=true
toprint()
: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
.
source to share