Merge and sync stdout and stderr?

It is a bit tricky, since you need to poll the stdout and stderr file descriptors of the subprocess while it's running, to get accurate timestamps. You also need to chop up the output into a list of lines so the final results can be merged and sorted easily. You could easily merge the two streams as they're read, but that wasn't part of the question.

It is a bit tricky, since you need to poll the stdout and stderr file descriptors of the subprocess while it's running, to get accurate timestamps. You also need to chop up the output into a list of lines so the final results can be merged and sorted easily. You could easily merge the two streams as they're read, but that wasn't 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 # prepend any data previously read, then split into lines and format buf = self.

_buf + buf tmp, rest = buf. Rsplit('\n', 1) self. _buf = rest now = datetime.datetime.now().isoformat() rows = tmp.

Split('\n') self. _rows += (now, '%s %s: %s' % (self. _name, now, r)) for r in rows def run(cmd, timeout=0.1): """ Run a command, read stdout and stderr, prefix with timestamp, and return a dict containing stdout, stderr and merged."""

PIPE = subprocess. PIPE proc = subprocess. Popen(cmd, stdout=PIPE, stderr=PIPE) streams = Stream('stdout', proc.

Stdout), Stream('stderr', proc. Stderr) def _process(drain=0): res = select. Select(streams, , , timeout) for stream in res0: stream.

Read(drain) while proc. Returncode is None: proc.poll() _process() _process(drain=1) # collect results, merge and return result = {} temp = for stream in streams: rows = stream. _rows temp += rows resultstream.

_name = r1 for r in rows temp.sort() result'merged' = r1 for r in temp return result res = run('ls', '-l', '. ', 'xyzabc') for key in ('stdout', 'stderr', 'merged'): print print '\n'. Join(reskey) print '-'*40 Example output: 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.

To merge properly, you need a sequence number in addition to the timestamp. The reason is that, when multiple lines are packed into a buffer, they all end up with the same timestamp. Python sorting is stable, however, so if you limit the sort key to just the timestamp, you don't need to introduce a sequence number.

– George Nov 20 at 5:59.

You can merge them passing subprocess. STDOUT as the stderr argument for subprocess. Popen, but I don't know if they will be formatted with time and source.

I would like it to be in addition to an stdout. Txt and stderr. Txt files, that is 3 outputs: 1.

Stdout, 2. Stderr, 3. Merge – user515766 Feb 13 at 14:14.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions