首页 > 解决方案 > 第一个结束后如何在 Node.js 中生成一个新的 Python 子进程?

问题描述

我在我的 node.js 应用程序中使用 Python 脚本的输出。

但是,我需要再查询一次(并且可能多次)。

我不能这样做,因为 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()

标签: javascriptpython-3.xspawnspawning

解决方案


您覆盖子进程。所以你不能再使用原来的对象(事件发射器)。

它可能比你更简单:)

只需在“start”函数中调用/移动事件发射器。因此,每次生成子对象时,都会使用新的子对象/事件发射器。

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! [ '3\n', '3\n', '3\n', '3\n', '3\n' ]

我以为你实际上是从标准输入读入你的 python 脚本。(而且不仅是一个虚拟函数)

但是对于节点部分,它不应该有任何差异。

在 Ubuntu 18.04 x64 上测试,节点: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.writechild.stdin.endpython 现在也可以“启动”,dosnt 必须等待更多数据。

注意:我不知道 IPC/stdio“缓冲”是如何工作的。如果你处理大数据,也许你会过期一些可疑的东西。

此外,我们将写入“stdout”的python数据存储为数组中的数字interval_response,因为您只需计算我们写入“stdin”的数据的总和。


推荐阅读