以流动模式流式传输子进程输出

时间:2013-09-17 11:50:58

标签: javascript python node.js

我使用Python编写自定义命令行,使用“print”语句打印输出。我通过生成子进程并使用 child.stdin.write 方法向其发送命令,从Node.js中使用它。这是来源:

var childProcess = require('child_process'),
    spawn = childProcess.spawn;

var child = spawn('./custom_cli', ['argument_1', 'argument_2']);

child.stdout.on('data', function (d) {
  console.log('out: ' + d);
});

child.stderr.on('data', function (d) {
  console.log('err: ' + d);
});

//execute first command after 1sec
setTimeout(function () {
  child.stdin.write('some_command' + '\n');
}, 1000);

//execute "quit" command after 2sec
//to terminate the command line
setTimeout(function () {
  child.stdin.write('quit' + '\n');
}, 2000);

现在问题是我没有收到flowing mode中的输出。我希望在打印后立即从子进程获取输出,但只有在子进程终止时才会收到所有命令的输出(使用自定义cli的退出命令)。

3 个答案:

答案 0 :(得分:10)

您需要刷新子进程中的输出。

可能你认为这不是必要的,因为当测试并让输出在终端上发生时,库就会自动刷新(例如,当一行完成时)。当打印进入管道时(由于性能原因),这不会完成。

自己冲洗:

#!/usr/bin/env python

import sys, time

while True:
  print "foo"
  sys.stdout.flush()
  time.sleep(2)

答案 1 :(得分:5)

最好的方法是使用无缓冲模式的python标准输出。它将强制python将输出写入输出流,而无需冲洗自己。

例如:

var spawn = require('child_process').spawn,
child = spawn('python',['-u', 'myscript.py']); // Or in custom_cli add python -u myscript.py

child.stdout.on('data', function (data) {
    console.log('stdout: ' + data);
});

child.stderr.on('data', function (data) {
    console.log('stderr: ' + data);
});

答案 2 :(得分:0)

Python中,我正在使用sys.stdin.readline并产生最后一行:

def read_stdin():
    '''
        read standard input
        yeld next line
    '''
    try:
        readline = sys.stdin.readline()
        while readline:
            yield readline
            readline = sys.stdin.readline()
    except:
        # LP: avoid to exit(1) at stdin end
        pass

 for line in read_stdin():
     out = process(line)
     ofp.write(out)
     sys.stdout.flush()

以及在Node.js

var child = spawn(binpath, args);

    // register child process signals
    child.stdout.on('data', function (_data) {
        var data = Buffer.from(_data, 'utf-8').toString().trim();
        console.log(data);
    });
    child.stderr.on('data', function (data) {
        console.warn('pid:%s stderr:%s', child.pid, data);
    });
    child.stdout.on('exit', function (_) {
        console.warn('pid:%s exit', child.pid);
    });
    child.stdout.on('end', function (_) {
        console.warn('pid:%s ended', child.pid);
    });
    child.on('error', function (error) {
        console.error(error);
    });
    child.on('close', (code, signal) => { // called after `end`
        console.warn('pid:%s terminated with code:%d due to receipt of signal:%s with ', child.pid, code, signal);
    });
    child.on('uncaughtException', function (error) {
        console.warn('pid:%s terminated due to receipt of error:%s', child.pid, error);
    });