【问题标题】:Stream child process output in flowing mode流模式下的流子进程输出
【发布时间】:2013-09-17 11:50:58
【问题描述】:

我有使用 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 的 quit 命令),我才会收到所有命令的输出。

【问题讨论】:

    标签: javascript python node.js


    【解决方案1】:

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

    您可能认为这没有必要,因为当测试并让输出发生在终端上时,库会自行刷新(例如,当一行完成时)。打印到管道时不会这样做(由于性能原因)。

    冲洗自己:

    #!/usr/bin/env python
    
    import sys, time
    
    while True:
      print "foo"
      sys.stdout.flush()
      time.sleep(2)
    

    【讨论】:

    • 非常感谢我的朋友,我被困了好几个小时。我相信你知道这种感觉。你有我永远的感激之情!
    【解决方案2】:

    最好的方法是使用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);
    });
    

    【讨论】:

      【解决方案3】:

      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);
          });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-06
        • 1970-01-01
        • 2019-06-03
        • 2011-03-05
        • 2015-08-23
        • 1970-01-01
        • 2019-05-26
        相关资源
        最近更新 更多