Как создать новый дочерний процесс Python в Node.js после того, как закончится первый?

#javascript #python-3.x #spawn #spawning

#javascript #python-3.x #порождение #порождение

Вопрос:

Я использую вывод скрипта Python в своем node.js приложение.

Однако мне нужно запросить его в другой раз (и, возможно, несколько раз).

Я не могу этого сделать, потому что процесс Python завершается и не может быть перезапущен. Я попытался переназначить переменную, но это не сработало. Как снова запустить скрипт Python? Вот мой код:

 var spawn = require('child_process').spawn,
interval_data = [1,2,4,5,6,7],
interval_dataString = '';

var py = undefined

startPython()

py.stdout.on('data', function(data){
  interval_dataString  = data.toString();
  console.log(interval_dataString)
});
  

py.stdout.on('end', function(){

  console.log('Alpha Component =',interval_dataString);
  
  setTimeout(() => {
    startPython()
  },1000)

});


function startPython() {
  py = undefined
  py = spawn('python', ['dfa.py'])
  py.stdin.write(JSON.stringify(interval_data));
  py.stdin.end();
}
 

Вот код Python:

 ## compute_input.py

import sys, json, numpy as np

#Read data from stdin
def read_in():
    
    lines = sys.stdin.readlines()
    #Since our input would only be having one line, parse our JSON data from that
    
    return json.loads(lines[0])
    
    #lines = "[1,2]" # for testing
    #return json.loads(lines) # for testing

def main():
    #get our data as an array from read_in()
    lines = read_in()

    #create a numpy array
    np_lines = np.array(lines)

    #use numpys sum method to find sum of all elements in the array
    lines_sum = np.sum(np_lines)

    #return the sum to the output stream
    print(lines_sum)

#start process
if __name__ == '__main__':
    main()
 

Комментарии:

1. Можете ли вы опубликовать свой код на Python? Итак, я могу протестировать свой пример

2. Привет, @Marc добавил мой код на python!

Ответ №1:

Вы переопределяете дочерний процесс. Таким образом, вы больше не можете использовать исходный объект (источник события).

Это проще, чем вы думали, может быть 🙂

Просто вызовите / переместите элемент источника событий внутри функции «пуск». Итак, каждый раз, когда вы создаете дочерний объект, вы используете новый дочерний объект / источник событий.

 const { spawn } = require("child_process");

const interval_data = [1, 2, 4, 5, 6, 7]
const interval_response = [];

// use this as exit strategie
var should_restart = true;


function start() {

    // spawn python child
    let child = spawn("python3", ["dfa.py"]);

    // would be better to work on buffer objects
    // create on final child/python exit a string out of the buffer
    child.stdout.on("data", (data) => {
        interval_response.push(data.toString());
    });

    // listen for the close event
    child.on("close", () => {
        if (should_restart) {

            // feedback
            console.log("Alpha Component =", interval_response.join());

            setTimeout(() => {
                start();
            }, 1000)

        } else {

            // nope, not now!
            console.log("DIE!", interval_response);
        
            // Do what ever you want with the result here

        }
    });

    // write stuff to python child process
    child.stdin.write(JSON.stringify(interval_data));

}

start();


// let the programm run for min. 5sec
setTimeout(() => {
    should_restart = false;
}, 5000);
 

Протестировано с вашим кодом на python.

 node index.js
Alpha Component = 3

Alpha Component = 3
,3

Alpha Component = 3
,3
,3

Alpha Component = 3
,3
,3
,3

DIE! [ '3n', '3n', '3n', '3n', '3n' ]
 

Я думал, вы на самом деле читаете в своем скрипте python из stdin. (И не только фиктивная функция)

Но для части узла это не должно иметь никакого значения.

Протестировано на Ubuntu 18.04 x64, node: v13.14.0, python: 3.6.9.

Редактировать:

Создан на основе вашего фрагмента python, скрипта, который считывает из стандартного набора и создает сумму из всех переданных чисел:

 import sys, json

def main():

    data = sys.stdin.read()
    data = json.loads(data)

    #print("debug:", data)

    chunks_sum = sum(data)

    #print("debug", chunks_sum)

    sys.stdout.write(str(chunks_sum))

#start process
if __name__ == '__main__':
    main()
 

Измененная функция запуска:

 function start() {

    // spawn python child
    let child = spawn("python3", ["dfa.py"]);

    // would be better to work on buffer objects
    // create on final child/python exit a string out of the buffer
    child.stdout.on("data", (data) => {

        // since your python code just create
        // a sum of all numbers, store the 
        // returend stuff as number
        interval_response.push(Number(data));

    });

    // listen for the close event
    child.on("close", () => {
        if (should_restart) {

            // feedback
            console.log("Alpha Component =", interval_response);

            setTimeout(() => {
                start();
            }, 1000)

        } else {

            // nope, not now!
            console.log("DIE!", interval_response);

            // create sum of all sum chunks from python
            // not sure what you want to do with the "interval_response" array
            // just for demo purpose
            let sum = interval_response.reduce((pv, cv) => pv   cv, 0);

            console.log("Total sum", sum);

        }
    });

    // write stuff to python child process
    //child.stdin.write();

    child.stdin.end(JSON.stringify(interval_data));

}
 

Изменено child.stdin.write на child.stdin.end , так что теперь python может «запуститься», и dosnt должен ждать дополнительных данных.

Примечание: я не знаю, как работает «буферизация» IPC / stdio. Возможно, вы сталкиваетесь с некоторыми подозрительными вещами, если работаете с большими данными.

Более того, мы сохраняем данные из python, которые записываются в «стандартный вывод», как число в массиве interval_response , поскольку вы просто вычисляете общую сумму данных, которые мы записываем в «стандартный вывод».

Комментарии:

1. Спасибо за ответ, но на самом деле, если мы читаем ввод JS в python, скрипт не работает. Я изменил приведенный выше скрипт python, пожалуйста, проверьте, по какой-то причине он не работает с этой модификацией… Вы знаете, почему? Если я добавлю py.stdin.end(); , это сработает, но только один раз.