3

I am trying to design a python script to control a command line simulator program written in C, including parsing output values printed to the screen, and giving input commands.

So far I am able to capture the initial boot up output from the simulator, but it hangs at the end.

Basically how I have it set up, is I set up the subprocess:

proc = Popen('./sim1',stdin=PIPE,stdout=PIPE)

then I have a for loop to process the output and display it to the screen (this is for testing purposes, I will be taking specific values from the text output later)

for line in iter(proce.stdout.readline,''):
    print(line.rstrip())

This hangs after all the text is printed, even though I added fflush(stdout) lines to the simulator below the printf statements (suggested here: catching stdout in realtime from subprocess)

I have added a exception that will break the loop if it detects a keyword on the last line, but it is not a very elegant solution that I would like to avoid.

After this loop I have code that inputs commands to the simulator, which I can tell work because if I remove the code to read the output from the simulator, the exit commands I send do exit the simulator.

It seems most of the examples I have seen are where people start the subprocess, capture output, and display it after the process exits. I need to capture output, display the output, and then give new commands, and display the next output, all without exiting the subprocess.

Is there something fundamental here that is causing my stdout issues?

Community
  • 1
  • 1
how2s101
  • 31
  • 1
  • If I understand well what you want, you are doing it the wrong way. Check http://stackoverflow.com/questions/3762881/how-do-i-check-if-stdin-has-some-data. – Antonis Christofides Dec 01 '16 at 19:28

1 Answers1

2

This is what I have and it works. You can replace the logger.info calls with print in your case.

import subprocess as sp

def run_long_running_cmd(args, responders=None):
    process = sp.Popen(args, stdout=sp.PIPE, stderr=sp.STDOUT)
    with process.stdout:
        while True:
            output = process.stdout.readline()
            exit_status = process.poll()
            if responders is not None:
                for responder in responders:
                    response = responder(output)
                    if response is not None:
                        process.stdin.write(response)
            if output:
                logger.info('\t' + output.rstrip())
            elif exit_status is not None:
                break

    logger.info('Finished running subprocess.')
    return exit_status
tvt173
  • 1,746
  • 19
  • 17
  • This will give me the same issue though, because I need the code to move beyond the while True: portion of the code, without exiting the subprocess. I want to give multiple input commands (using stdin) and read the output that occurs between each command. – how2s101 Dec 01 '16 at 21:26
  • Sounds like maybe you need to trigger an event in this loop and subscribe to that event with a delegate that will respond to a certain stdout output – tvt173 Dec 01 '16 at 21:37
  • That's somewhat the path I'm going down now, where I've added an escape code to the simulator indicating end of current prompt. It's workingish but because of the way the simulator is set up it would be a very lengthy full implementation. – how2s101 Dec 01 '16 at 21:47
  • What about something like the above? (disclaimer: I haven't tested the new code) – tvt173 Dec 01 '16 at 21:47
  • I ended up going in a different direction, with having a simulator write to a formatted file, and reading from there, but I will try out the update from you as soon as I can. – how2s101 Dec 05 '16 at 03:14