Node.js中的Python子脚本输出在完成时,而非实时

7 投票
1 回答
2655 浏览
提问于 2025-04-19 05:27

我刚接触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))

这是服务器的简化版本:

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');
    });

最后是网页的内容:

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>

问题是,node.js似乎一次性收到了所有的温度值,而不是在随机的时间间隔内收到10个温度值。结果是我在脚本结束后,收到了一个长长的字符串,里面包含了所有的值:

很多温度值 控制台输出

1 个回答

13

你需要在Python中关闭输出缓冲。这可以通过很多不同的方法来实现,包括:

  • 设置环境变量 PYTHONUNBUFFERED
  • 在运行Python程序时加上 -u 这个选项
  • 在每次写入标准输出(也就是你用 print() 打印内容的时候)后调用 sys.stdout.flush()
  • 如果你用的是Python 3.3及以上版本,可以在 print() 中加上 flush=True,像这样: print('Hello World!', flush=True)

另外,在你的节点代码中,尽管你的Python代码里有一个睡眠(也就是暂停)并且你现在在刷新标准输出,但你真的不应该假设在 thermostat.stdout 的 'data' 处理器中, output 总是只有一行。

撰写回答