使用python-shell在JS环境中运行Python代码时消息不同步问题
问题:python-shell执行Python代码时消息输出不同步
我用python-shell在JavaScript环境中运行一段会返回多条消息的Python代码,但遇到了消息不同步的问题——第一条消息能在正确时机返回,但后续所有消息会在最后一次性返回,而非逐条输出。
单独运行test.py时消息输出正常,说明问题不在Python代码本身。从每条消息的time:字段能看出,Python代码里各条消息的执行时机是对的,但在浏览器环境中,<2>FIRST TEST会先打印,<3>TEST和<4>MORE TEST要等10秒后才一起打印。

我的代码
Python代码(test.py)
import sys import time import threading def test(): start = time.time() end1 = time.time() print("<2>FIRST TEST time: {}".format(end1 - start)) time.sleep(5) end2 = time.time() print("<3>TEST time: {}".format(end2 - start)) time.sleep(5) end3 = time.time() print("<4>MORE TEST time: {}".format(end3 - start)) x = threading.Thread(target=test) x.start() sys.stdout.flush()
JavaScript代码(execPyShell.ts)
const exec: () => void = () => { console.log('Start') let pyshell = new PythonShell('./engine/test.py'); let newLogs: string[] = []; pyshell.on('message', function(message: string) { console.log(message); }) pyshell.end(function (err: any) { if (err){ throw err; }; console.log('Finished'); }); }
解决办法
问题根源是Python的标准输出默认有缓冲机制,子线程中的print输出被缓存,直到线程结束才一次性发送给JavaScript端。可以通过两种方式解决:
方式一:每次print后手动刷新缓冲区
修改Python代码,在每个print语句后调用sys.stdout.flush(),同时主线程等待子线程结束:
import sys import time import threading def test(): start = time.time() end1 = time.time() print("<2>FIRST TEST time: {}".format(end1 - start)) sys.stdout.flush() time.sleep(5) end2 = time.time() print("<3>TEST time: {}".format(end2 - start)) sys.stdout.flush() time.sleep(5) end3 = time.time() print("<4>MORE TEST time: {}".format(end3 - start)) sys.stdout.flush() x = threading.Thread(target=test) x.start() x.join() # 等待子线程执行完毕 sys.stdout.flush()
方式二:禁用Python输出缓冲(更简便)
在python-shell的配置中添加-u参数,让Python以无缓冲模式运行,这样所有print内容会实时输出:
const exec: () => void = () => { console.log('Start') let pyshell = new PythonShell('./engine/test.py', { pythonOptions: ['-u'] // 启用无缓冲输出 }); let newLogs: string[] = []; pyshell.on('message', function(message: string) { console.log(message); }) pyshell.end(function (err: any) { if (err){ throw err; }; console.log('Finished'); }); }
内容的提问来源于stack exchange,提问作者anti-duhring
相关产品推荐
相关产品推荐

