我正在尝试制作机器学习项目(整数序列预测器)。 ML代码是一个python脚本。我试图建立一个快速路由来处理python脚本的stdin和stdout并根据它发送响应。
我在应用程序启动时生成python脚本。
let p = spawn('python', ['python/script.py'], { stdio: ['pipe', 'pipe', process.stderr] });
我的路线
router.get('/', managePredictor);
managePredictor
function managePredictor(req, res, next) {
try {
//timestamp
let ts = new Date().getTime();
let token = ts + '_' + magic();
let seq = req.query.seq;
let re = new RegExp(token + '((?:\\s|\\S)*)' + token);
p.stdin.write(token + '\n' + seq + '\n');
p.stdout.resume();
p.stdout.on('data', (chunk) => {
str += chunk;
let s = re.exec(str);
let o = JSON.parse(s[1].trim());
p.stdout.pause();
res.send(o);
});
}
catch (err) {
res.status(500).send('Internal Server Error');
}
}
token
是一个类似1520661269162_YGo6p3
的字符串。
对于路线的第一次请求,但对于任何连续请求,错误就像
>Error: Can't set headers after they are sent.
> at validateHeader (_http_outgoing.js:494:11)
> at ServerResponse.setHeader (_http_outgoing.js:501:3)
> at ServerResponse.header (D:\mlproj\node_modules\express
>lib\response.js:730:10)
> at ServerResponse.send (D:\mlproj\node_modules\express >\lib\response.js:170:12)
> at ServerResponse.json (D:\mlproj\node_modules\express >\lib\response.js:256:15)
> at ServerResponse.send (D:\mlproj\node_modules\express >\lib\response.js:158:21)
at Socket.p.stdout.on (D:\mlproj\routes\predict.js:39:11)
at emitOne (events.js:121:20)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
Python脚本的IO片段
while True:
ts = input()
inp = input()
arr = inp.split(" ")
arr = list(map(lambda x: int(x), arr))
qq = findNextn(arr, 5)
print(ts)
out = json.dumps({'orignal': arr, 'predicted':qq}, indent=4)
print(out)
print(ts)
答案 0 :(得分:1)
p.stdout.on('data', (chunk) => { ... res.send(o);
每次收到大量数据时都会尝试发送响应。
因此,在请求到达后第一次获得大量数据时,您会发送响应。
然后,当您下次获得一大块数据时,您会尝试再次发送响应。你不能这样做,因为它已经被发送了。
您需要重新思考如何处理HTTP请求与Python程序中的数据之间的交互。
每次从Python进程获取一个块时,您应该将数据存储在一个字符串中,然后使用该字符串的当前内容响应HTTP请求(同时将其重置为空字符串)。
答案 1 :(得分:1)
您需要使用node streams。
以下代码应该有效。
function managePredictor(req, res, next) {
try {
//timestamp
let ts = new Date().getTime();
let token = ts + '_' + magic();
let seq = req.query.seq;
let re = new RegExp(token + '((?:\\s|\\S)*)' + token);
p.stdin.write(token + '\n' + seq + '\n');
p.stdout.on('open', () => {
res.pipe(p.stdout)
})
p.stdout.on('data', (chunk) => {
str += chunk;
let s = re.exec(str);
let o = JSON.parse(s[1].trim());
p.stdout.write(o);
});
p.stdout.on('end', (chunk) => {
res.end();
});
}
catch (err) {
res.status(500).send('Internal Server Error');
}
}