Вопрос

I am working with a python script that runs on a loop and outputs a new value every second, and can only be stopped by pressing enter on the keyboard. For various reasons, the python code should not be altered.

Ask: How do I capture the first ten values of the looping script then kill the script from Node?

I wrote the below Node script that will kick off an external program and log the output; however, this only works for scripts that aren't running in loops.

var exec = require('child_process').exec;
var scriptCommand = "sudo python script.py"

exec(scriptCommand, function cb(error, stdout, stderr){
  console.log('stdout: ' + stdout);
  console.log('stderr: ' + stderr); 
  if (error !== null){
    console.log('exec error: ' + error);
  }
});
Это было полезно?

Решение

You're going to want to use spawn and capture the standard output of the python child process. Once you have reached ten values, you can kill the python process.

Unfortunately you're going to have to modify the python program to flush stout. There is no way around this. If you do not manually flush stdout, python will, but only after the internal buffer fills up (which in my sample code will take awhile).

Here is a fully working example (captures first three values and then kills the python process):

pyscript.py

#!/usr/bin/env python
# python 2.7.4
import time
import sys

i = 0
while(True):
    time.sleep(1)
    print("hello " + str(i))

    # Important! This will flush the stdout buffer so node can use it
    # immediately. If you do not use this, node will see the data only after
    # python decides to flush it on it's own.
    sys.stdout.flush()

    i += 1

script.js

#!/usr/bin/env node
"use strict";
// node version 0.10.26

var spawn = require('child_process').spawn
, path = require('path')
, split = require('split');

// start the pyscript program
var pyscript = spawn('python', [ path.join(__dirname, 'pyscript.py') ]);

var pythonData = [];

// Will get called every time the python program outputs a new line.
// I'm using the split module (npm) to get back the results
// on a line-by-line basis
pyscript.stdout.pipe(split()).on('data', function(lineChunk) {
    // Kill the python process after we have three results (in our case, lines)
    if (pythonData.length >= 3) {
        return pyscript.kill();
    }

    console.log('python data:', lineChunk.toString());
    pythonData.push(lineChunk.toString());
});

// Will be called when the python process ends, or is killed
pyscript.on('close', function(code) {
    console.log(pythonData);
});

Put them both in the same directory, and make sure to grab the split module for the demo to work.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top