Как правильно совершать последовательные вызовы дочернего процесса в Node.js? - PullRequest
0 голосов
/ 25 января 2019

У меня есть приложение Node.js, которое в настоящее время является веб-интерфейсом API. Для одной из моих функций API я вызываю короткий сценарий Python, который я написал для достижения некоторой дополнительной функциональности.

После прочтения связи между Node и Python с использованием модуля child_process я попробовал и достиг желаемых результатов. Я вызываю функцию Node, которая принимает адрес электронной почты, отправляет его на Python через std.in, мой скрипт Python выполняет необходимый внешний вызов API, используя предоставленную электронную почту, и записывает вывод внешнего вызова API в std.out и отправляет его обратно в мою функцию узла.

Все работает правильно, пока я не сработаю несколько запросов подряд. Несмотря на то, что Python правильно регистрирует измененный адрес электронной почты, а также делает запрос к внешнему API с обновленным адресом электронной почты, после первого запроса к моему API (возвращающему правильные данные) я продолжайте получать одни и те же старые данные снова и снова.

Мое первоначальное предположение заключалось в том, что поток ввода Python не очищался, но после тестирования сценария Python я увидел, что правильно обновляю адрес электронной почты, получаемый от Node, и получаю правильные результаты запроса.

Я думаю, что есть некоторые основные принципы работы модуля child_process, которые я, возможно, не понимаю ... так как я достаточно уверен, что соответствующие данные правильно передаются взад и вперед.

Ниже приведена функция узла:

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 все возвращается идеально. Только после нескольких вызовов я застреваю, возвращая один и тот же вывод снова и снова.

Я бью стену здесь, и любая помощь будет принята с благодарностью. Спасибо всем!

1 Ответ

0 голосов
/ 25 января 2019

Я использовал замок Mutex для такого рода примера.Похоже, я не могу найти вопрос, откуда исходит код, поскольку я обнаружил его в 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 ... но это должно по крайней мере дать вам хорошийначать.

...