So I think I've rolled my own with a couple of threads.
For the example below, test.py
is this:
#!/usr/bin/python -u
import sys
import time
sys.stdout.write("stdout 1\n")
time.sleep(1)
sys.stderr.write("stderr 2\n")
time.sleep(1)
sys.stdout.write("stdout 3\n")
time.sleep(1)
sys.stderr.write("stderr 4\n")
time.sleep(1)
My code for getting the right output is:
#!/usr/bin/env python
import subprocess
from threading import Thread, Lock
cmdOutput = []
cmdOutputLock = Lock()
STDOUT = 1
STDERR = 2
def _outputLoop( fd, identifier ) :
line = fd.readline()
while line :
cmdOutputLock.acquire()
cmdOutput.append( ( line, identifier ) )
cmdOutputLock.release()
line = fd.readline()
p = subprocess.Popen( "test.py",
stdout = subprocess.PIPE,
stderr = subprocess.PIPE )
Thread( target=_outputLoop, args=( p.stdout, STDOUT ) ).start()
Thread( target=_outputLoop, args=( p.stderr, STDERR ) ).start()
while fd.poll() is None or cmdOutput :
output = None
cmdOutputLock.acquire()
if cmdOutput :
output = cmdOutput[0]
del cmdOutput[0]
cmdOutputLock.release()
if output :
if output[1] == STDOUT :
print "STDOUT : {}".format( output[0].rstrip() )
elif output[1] == STDERR :
print "STDERR : {}".format( output[0].rstrip() )
I can definitely imagine a time when an stderr line is mixed up with an stdout line, but for the sake of what I wanted it for, it certainly works. (I was putting this as part of a logging module which would run a command and use different log levels for stdout and stderr.)