【问题标题】:How do I correctly make consecutive calls to a child process in Node.js?如何正确连续调用 Node.js 中的子进程?
【发布时间】:2019-01-25 17:14:48
【问题描述】:

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

在阅读了使用 child_process 模块在 Node 和 Python 之间进行通信之后,我尝试了一下,并达到了我想要的结果。我调用接收电子邮件地址的 Node 函数,通过std.in 将其发送到 Python,我的 Python 脚本使用提供的电子邮件执行必要的外部 API 调用,并将外部 API 调用的输出写入std.out并将其发送回我的节点函数。

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

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

我认为 child_process 模块的一些基本工作原理我可能不理解......因为我相当确定相应的数据正在正确地来回传递。

下面是Node函数:

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;

  }

这里是 Python 脚本:

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()

再次,在对callPythonScript 进行单次 调用后,一切都会完美返回。只有在进行多次调用时,我才会一遍又一遍地返回相同的输出。

我在这里碰壁了,我们将不胜感激。谢谢大家!

【问题讨论】:

  • 我正在做类似的事情,但我认为你想要你的 stderr.on 在你的 stdout.on 之前
  • 所以我交换了顺序并将我的stderr.on 放在我的两个stdout.on 之前。问题仍然存在。您介意分享您对原因的见解吗?
  • 对不起,我在发表上一条评论时只是想了半天,这不是解决您问题的方法。我为解决这个问题所做的就是编写一个互斥锁类。这样就可以进行一系列操作,但要一次处理一个。
  • 别担心,我认为您只是在为更好的组织提供一些见解。我开始觉得我需要深入研究一些多线程才能使其正常工作。你介意分享一些关于你的 Mutex Lock 类的信息吗,也许是通过 PM 或分享一个 git repo?

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


【解决方案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的每个数组值的地方......但这至少应该给你一个好的开始。

【讨论】:

  • 非常感谢您的洞察力。我的callPythonScript 目前未包含在任何课程中,但我认为这给了我一个很好的起点。我会开始修补东西,如果很快没有神奇的解决方案出现(很确定它不会大声笑),我会接受你的。再次感谢
  • 是的,我最近才开始接触 JS,并立即开始使用类。我从来没有真正正确地了解原型之类的......但它应该很容易混合和匹配我所拥有的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 2023-03-02
  • 1970-01-01
  • 2017-03-01
相关资源
最近更新 更多