Reading Live Output from a Subprocess
Chris Rebert
clp2 at rebertia.com
Fri Apr 6 03:30:11 EDT 2012
On Thu, Apr 5, 2012 at 11:57 PM, <bunslow at gmail.com> wrote:
> Okay, I've been trying for days to figure this out, posting on forums, Googling, whatever. I have yet to find a solution that has worked for me. (I'm using Python 3.2.2, Ubuntu 11.04.) Everything I've tried has led to buffered output being spat back all at once after the subprocess terminates. I need this functionality because the script I am currently writing is only glue, and most of the work is done by a subprocess (which could potentially run for a long time).
<snip>
> Not a single one of the solutions above has worked for me. I've tried
>
> ######################################
> import subprocess as sub
> out = sub.Popen(["pypy", "5"], universal_newlines=True, stdout=sub.PIPE, stderr=sub.STDOUT, bufsize=1)
>
> line = out.stdout.readline()
> out.stdout.flush()
> while line:
> print(line)
> line = out.stdout.readline()
> out.stdout.flush()
You're flush()-ing the wrong stream here. The process's stdout is an
incoming stream from Python's perspective, which makes flushing it
pointless AFAIK. You want to flush *Python*'s stdout (that you're
print()-ing to). Which would be:
import sys
for line in out.stdout:
print(line)
sys.stdout.flush()
> ######################################
>
> I've tried
>
> ######################################
> line = out.stdout.readline()
> while line:
> print(line)
> line = out.stdout.readline()
Less repetitively written:
while True:
line = out.stdout.readline()
if not line:
break
print(line)
Or more idiomatically written:
# I hope this was the first thing you tried?
for line in out.stdout:
print(line)
> ######################################
>
> I've tried
>
> ######################################
> for line in out.readline():
> print(line)
(I assume you meant "out.stdout"? "out" is a bad name anyway; it's a
process, not an output stream.)
This iterates over individual characters in the first line of the
output. In "for X in Y", Y only gets evaluated once.
> ######################################
>
> I've tried
>
> ######################################
> for line in out.communicate():
> print(line)
That's the explicitly-documented-as-blocking method, the exact
opposite of what you want.
Cheers,
Chris
More information about the Python-list
mailing list