如何在Node.js中正确地连续调用子进程?

时间:2019-01-25 17:14:49

标签: python node.js multithreading process child-process

我有一个Node.js应用程序,该应用程序当前是基于Web的API。对于我的API函数之一,我调用了为实现某些额外功能而编写的简短Python脚本。

在学习了使用child_process模块在​​Node和Python之间的通信之后,我做了一次尝试,并取得了想要的结果。我调用接收电子邮件地址的Node函数,然后通过std.in将其发送到Python,我的Python脚本使用提供的电子邮件执行必要的外部API调用,并将外部API调用的输出写入{ {1}}并将其发送回我的Node函数。

一切正常,直到我连续发出多个请求。尽管Python正确记录了更改后的电子邮件地址,并使用更新后的电子邮件地址向外部API发出了请求,但在我对 my API发出第一个请求后(返回了正确的数据),我不断收到相同的旧数据。

我最初的猜测是没有清除Python的输入流,但是在测试Python脚本之后,我看到我正确地更新了从Node接收的电子邮件地址并接收了正确的查询结果。

我认为child_process模块​​的某些底层工作可能我还不了解...因为我相当确定相应的数据已正确地来回传递。

下面是Node函数:

std.out

这是Python脚本:

exports.callPythonScript = (email)=>
{
    let getPythonData = new Promise(function(success,fail){

    const spawn = require('child_process').spawn;
    const pythonProcess = spawn('python',['./util/emailage_query.py']);

    pythonProcess.stdout.on('data', (data) =>{
      let dataString = singleToDoubleQuote(data.toString());
      let emailageResponse = JSON.parse(dataString);
      success(emailageResponse);
    })

    pythonProcess.stdout.on('end', function(){
      console.log("python script done");
    })

    pythonProcess.stderr.on('data', (data) => {
      fail(data);
    })

    pythonProcess.stdin.write(email);
    pythonProcess.stdin.end();

    })

    return getPythonData;

  }

同样,对import sys from emailage.client import EmailageClient def read_in(): lines = sys.stdin.readlines() return lines[0] def main(): client = EmailageClient('key','auth') email = read_in() json_response = client.query(email,user_email='authemail@mail.com') print(json_response) sys.stdout.flush() if __name__ == '__main__': main() 进行单个调用后,一切都会完美返回。只有在进行多次调用后,我才能一遍又一遍地返回相同的输出。

我在这里碰壁,任何帮助都将不胜感激。谢谢大家!

1 个答案:

答案 0 :(得分:1)

对于这种示例,我使用了互斥锁。我似乎找不到代码的问题,因为当我遇到类似问题时,我在SO上发现了这个问题:

class Lock {
  constructor() {
    this._locked = false;
    this._waiting = [];
  }

  lock() {
    const unlock = () => {
      let nextResolve;
      if (this._waiting.length > 0) {
        nextResolve = this._waiting.pop(0);
        nextResolve(unlock);
      } else {
        this._locked = false;
      }
    };
    if (this._locked) {
      return new Promise((resolve) => {
        this._waiting.push(resolve);
      });
    } else {
      this._locked = true;
      return new Promise((resolve) => {
        resolve(unlock);
      });
    }
  }
}

module.exports = Lock;

接下来我将在其中调用的代码将通过您的代码实现:

class Email {
  constructor(Lock) {
    this._lock = new Lock();
  }

  async callPythonScript(email) {
    const unlock = await this._lock.lock();
    let getPythonData = new Promise(function(success,fail){

    const spawn = require('child_process').spawn;
    const pythonProcess = spawn('python',['./util/emailage_query.py']);

    pythonProcess.stdout.on('data', (data) =>{
      let dataString = singleToDoubleQuote(data.toString());
      let emailageResponse = JSON.parse(dataString);
      success(emailageResponse);
    })

    pythonProcess.stdout.on('end', function(){
      console.log("python script done");
    })

    pythonProcess.stderr.on('data', (data) => {
      fail(data);
    })

    pythonProcess.stdin.write(email);
    pythonProcess.stdin.end();

    })
    await unlock();
    return getPythonData;
  }
}

我还没有测试过这段代码,并且已经实现了我要处理数组以及每个数组值调用python的地方……但这至少应该为您提供一个良好的开端。