Javascript 我能';我不明白为什么我的快速路线会遇到';can';t在发送标题后设置标题';
我正在尝试做一个机器学习项目(整数序列预测器)。ML代码是一个python脚本。我正在尝试创建一个快速路由来处理python脚本的stdin和stdout,并根据它发送响应 我在应用程序启动时生成python脚本Javascript 我能';我不明白为什么我的快速路线会遇到';can';t在发送标题后设置标题';,javascript,node.js,express,Javascript,Node.js,Express,我正在尝试做一个机器学习项目(整数序列预测器)。ML代码是一个python脚本。我正在尝试创建一个快速路由来处理python脚本的stdin和stdout,并根据它发送响应 我在应用程序启动时生成python脚本 let p = spawn('python', ['python/script.py'], { stdio: ['pipe', 'pipe', process.stderr] }); 我的路线 router.get('/', managePredictor); managePred
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)
您尝试在每次获得一块数据时发送响应
因此,在请求到达后第一次获得数据块时,您会发送一个响应
然后,下次当您获得一块数据时,您会再次尝试发送响应。您不能这样做,因为它已被发送
您需要重新考虑如何处理HTTP请求和Python程序中的数据之间的交互 可能您应该在每次从Python进程获取块时将数据存储在一个字符串中,然后使用该字符串的当前内容响应HTTP请求(同时将其重置为空字符串) 您尝试在每次获得一块数据时发送响应 因此,在请求到达后第一次获得数据块时,您会发送一个响应 然后,下次当您获得一块数据时,您会再次尝试发送响应。您不能这样做,因为它已被发送
您需要重新考虑如何处理HTTP请求和Python程序中的数据之间的交互 每次从Python进程获取块时,您可能都应该将数据存储在一个字符串中,然后使用该字符串的当前内容响应HTTP请求(同时将其重置为空字符串)。您需要为此使用 下面的代码应该可以工作
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');
}
}
你需要用这个
下面的代码应该可以工作
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');
}
}
这在我的情况下不起作用,因为我没有为每个人生成python进程,但我正在尝试处理一个已经生成的进程的stdin/stdout,该进程在应用程序启动后生成。这应该仍然适用于您。您得到的错误是什么?
无效数据,区块必须是字符串或缓冲区,而不是对象
好的,它应该是字符串现在更正错误后,我再也没有得到响应。可能是因为在我的python脚本中,永远都在运行,期待I/O,这就是为什么当应用程序终止时,这个流不应该工作。因此,我需要找到其他解决方案。这在我的情况下不起作用,因为我不是为每个人生成python进程,但我正在尝试处理一个已经生成的进程的stdin/stdout,该进程在应用程序启动后生成。这应该仍然适用于您。您得到的错误是什么?无效数据,区块必须是字符串或缓冲区,而不是对象
好的,它应该是字符串现在更正错误后,我再也没有得到响应。可能是因为在我的python脚本中,永远都在运行,期待I/O,这就是为什么当应用程序终止时,这个流不应该工作。所以我需要找到其他的解决办法。