Node.js的python子脚本在完成时输出,而不是实时

mbd*_*vis 5 python buffer stdout node.js socket.io

我是node.js和socket.io的新手,我正在尝试编写一个基于python输出更新网页的小服务器.

最终这将用于温度传感器,所以现在我有一个虚拟脚本,每隔几秒打印一次温度值:

Thermostat.py

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

这是服务器的缩减版本:

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');
    });
Run Code Online (Sandbox Code Playgroud)

最后是网页:

的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>
Run Code Online (Sandbox Code Playgroud)

问题是nodejs似乎一次收到所有温度值,而不是以随机间隔获得10个温度值,我在脚本完成后得到一个长字符串中的所有值:

很多临时值 控制台输出

msc*_*dex 8

你需要在python中禁用输出缓冲.这可以通过多种方式完成,包括:

  • 设置PYTHONUNBUFFERED环境变量
  • -u开关传递给python可执行文件
  • sys.stdout.flush()在每次写入(或print()在您的情况下)之后调用stdout
  • 对于Python 3.3+,您可以传递flush=trueprint():print('Hello World!', flush=True)

另外,在你的节点代码中,(即使你在你的python代码中有一个睡眠而你现在正在刷新stdout)你真的不应该假设output在你的'data'处理程序中thermostat.stdout总是只有一行.