Javascript 我能';我不明白为什么我的快速路线会遇到';can';t在发送标题后设置标题';

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

我正在尝试做一个机器学习项目(整数序列预测器)。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) 
您尝试在每次获得一块数据时发送响应

因此,在请求到达后第一次获得数据块时,您会发送一个响应

然后,下次当您获得一块数据时,您会再次尝试发送响应。您不能这样做,因为它已被发送


您需要重新考虑如何处理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,这就是为什么当应用程序终止时,这个流不应该工作。所以我需要找到其他的解决办法。