I want to capture output from a C program I’m launching like this:
p = subprocess.Popen(["make", "run_pci"],
stdout=subprocess.PIPE,
cwd="/home/ecorbett/hello_world_pthread")
for ln in p.stdout:
Only problem is I dont get output until the C program is done, when in fact I need to get output line by line as the program is running. And to further complicate matters, I have to parse each line ( i only need certain data from lines).
For example, here is some sample output: (I need to capture “Thread on Tile #”)
blahblah blah Thread blahblah blah tile 1: On
blahblah blah Thread blahblah blah tile 2: OFF
blahblah blah Thread blahblah blah tile 3 : Disable
I noticed the article I linked below seems to have the same problem. I was trying to figure how to adapt it to my situation?
Getting realtime output from ffmpeg to be used in progress bar (PyQt4, stdout)
Python newbie, so example code is greatly appreciated!!!
You can’t use p.stdout like that; if you ask for “the whole stdout”, this will only be available upon process termination (or pipe buffer filling, which could take a long time).
You need to read from the process’s stdout line by line.
It would also be best if stdout could be set to line buffered (usually it is fully buffered wherever possible), but I think this can only be done from within the called program.
We have two buffers to consider here. One is the C program’s output buffer. This may be nonexistent (unbuffered output), line buffered, or fully buffered (1K, 4K or 8K are some possible sizes).
Within the program, a “printf()” is called. The output goes:
Now the output enters Python’s pipe. This again may be fully buffered (stdout) or line buffered (readline). So the output goes:
In this last case, the buffer will go in 4K chunks to the Python logic.
Let us now imagine a line buffered C program outputting one line, 1K characters long, each second, to a Python program (if the C program is fully buffered, there’s not very much that can be done!)
Reading stdout in cycle, we would see (inside the for loop):
…
Reading through readline we would get:
EXAMPLE
Here I run “ping -c 3 -i 2 127.0.0.1” in order to get three packets to localhost at two seconds interval. One run of ping takes around six seconds. I read the output from ping, and print a timestamp. The whole output of ping is small enough that it fits in Python’s full-buffer.
The output I receive on my Linux box is, as expected: