This example seems to work for me:
# -*- Mode: Python -*- # vi:si:et:sw=4:sts=4:ts=4 import subprocess import sys import select p = subprocess.Popen(["find", "/proc"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout =  stderr =  while True: reads = [p.stdout.fileno(), p.stderr.fileno()] ret = select.select(reads, , ) for fd in ret: if fd == p.stdout.fileno(): read = p.stdout.readline() sys.stdout.write('stdout: ' + read) stdout.append(read) if fd == p.stderr.fileno(): read = p.stderr.readline() sys.stderr.write('stderr: ' + read) stderr.append(read) if p.poll() != None: break print 'program ended' print 'stdout:', "".join(stdout) print 'stderr:', "".join(stderr)
In general, any situation where you want to do stuff with multiple file descriptors at the same time and you don't know which one will have stuff for you to read, you should use select or something equivalent (like a Twisted reactor).
To print to console and capture in a string stdout/stderr of a subprocess in a portable manner:
from StringIO import StringIO fout, ferr = StringIO(), StringIO() exitcode = teed_call(["the", "command"], stdout=fout, stderr=ferr) stdout = fout.getvalue() stderr = ferr.getvalue()
teed_call() is defined in Python subprocess get children's output to file and terminal?
You could use any file-like objects (
Create two readers as above, one for
stdout one for
stderr and start each in a new thread. This would append to the list in roughly the same order they were output by the process. Maintain two separate lists if you want.
p = subprocess.Popen(["the", "command"]) t1 = thread.start_new_thread(func,stdout) # create a function with the readers t2 = thread.start_new_thread(func,stderr) p.wait() # your logic here