This is a bit tricky since you need to poll the file descriptors of the stdout and stderr subprocess while it is running to get the exact timestamps. You also need to cut the output to a list of strings so that the final results can be easily combined and sorted. You can easily combine the two streams as you read them, but this was not part of the question.
I wrote it quickly, but it could be made cleaner and more compact:
import datetime import os import select import subprocess class Stream(object): def __init__(self, name, impl): self._name = name self._impl = impl self._buf = '' self._rows = [] def fileno(self): "Pass-through for file descriptor." return self._impl.fileno() def read(self, drain=0): "Read from the file descriptor. If 'drain' set, read until EOF." while self._read() is not None: if not drain: break def _read(self): "Read from the file descriptor" fd = self.fileno() buf = os.read(fd, 4096) if not buf: return None if '\n' not in buf: self._buf += buf return []
Output Example:
stdout 2011-03-03T19:30:44.838145: .: stdout 2011-03-03T19:30:44.838145: total 0 stdout 2011-03-03T19:30:44.838338: -rw-r--r-- 1 pat pat 0 2011-03-03 19:30 bar stdout 2011-03-03T19:30:44.838518: -rw-r--r-- 1 pat pat 0 2011-03-03 19:30 foo ---------------------------------------- stderr 2011-03-03T19:30:44.837189: ls: cannot access xyzabc: No such file or directory ---------------------------------------- stderr 2011-03-03T19:30:44.837189: ls: cannot access xyzabc: No such file or directory stdout 2011-03-03T19:30:44.838145: .: stdout 2011-03-03T19:30:44.838145: total 0 stdout 2011-03-03T19:30:44.838338: -rw-r--r-- 1 pat pat 0 2011-03-03 19:30 bar stdout 2011-03-03T19:30:44.838518: -rw-r--r-- 1 pat pat 0 2011-03-03 19:30 foo ----------------------------------------
source share