Node.js's python child script outputting on finish, not real time

老子叫甜甜 提交于 2019-12-07 04:51:15

问题


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

Eventually this will be used for a temperature sensor so for now I have a dummy script which prints 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 a cut down 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 nodejs seems to recieve all of the temperature values at once, and instead of getting 10 temperature values at random intervals, I get all of the values in one long string after the script has finished:


回答1:


You need to disable output buffering in python. This can be done many different ways, including:

  • Setting the PYTHONUNBUFFERED environment variable
  • Passing the -u switch to the python executable
  • Calling sys.stdout.flush() after each write (or print() in your case) to stdout
  • For Python 3.3+ you can pass flush=true to print(): print('Hello World!', flush=True)

Additionally, in your node code, (even though you have a sleep in your python code and you are now flushing stdout) you really should not assume that output in your 'data' handler for thermostat.stdout is always going to be just one line.



来源:https://stackoverflow.com/questions/25607799/node-jss-python-child-script-outputting-on-finish-not-real-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!