[Chicago] capturing output from subprocesses
Noel Thomas Taylor
nttaylor at uchicago.edu
Wed Nov 23 00:49:10 CET 2005
Hi Jess,
I had not properly understood the difference before in how EOF is
registered when reading from a pipe vs. when reading from a pty. All is
much clearer now and I've implemented the code as you outlined below,
including separate tracking of the stdOut and stdErr buffers.
By the way, I removed one level of nesting by replacing:
for f in rl:
if f == outpi:
o = read(f, 100)
with:
if outpi in rl:
o = read(outpi, 100)
So far there seem to be no ill-effects, but I've been burned making
seemingly innocuous changes before, so I thought I'd bring it up.
Everything is still running fine on all platforms, and my understanding of
these functions is at an all-time high. Still, I'd like to ask you about
one of the more subtle tricks with pseudo-terminals.
I've read that sometimes when you're passing data through a
pseudo-terminal, it will change "\n" to "\r\n" and in this way your data,
especially binary data, can be corrupted.
Since I'm always passing text in my implementation, this isn't a big
problem, and I just replace all "\r" instances with the empty string.
o = read(f, 100).replace("\r","")
But if I *did* want to pass binary data, I'd be in trouble right? The
situation is made more complicated by the fact that the data might be
coming from a remote host.
Do you know a smooth way around this problem?
with thanks and best wishes for the holiday,
Noel Taylor
> So based on what was said above, this seems to be the better implementation:
>
> # finished flag
> end = 0
>
> for f in rl:
> if f == outpi:
> # we might not be able to read the pty
> # so we trap the error and signal end, we
> # don't break because there might be something
> # able to be read from "error" stream
> try:
> o = read(f, 100)
> except OSError, e:
> end = 1
> continue
> output += o
> elif f == errpi:
> # error stream is a pipe so we get a proper EOF
> # and can signal end from that
> e = read(f, 100)
> if e: error += e
> else: end = 1
>
> # exit the 'while 1' when nothing left to be read
> if end:
> break
>
> ------------------------------------
> Also, it's possible that if you have a very large amount of amount in
> one of the buffers that the other one will signal 'end' before you
> finish reading. So if you want it to be perfect, you should track
> 'end' for each (stdout and stderr) buffer individually and adjust the
> read's and read fdset accordingly.
>
> Jess
> _______________________________________________
> Chicago mailing list
> Chicago at python.org
> http://mail.python.org/mailman/listinfo/chicago
>
More information about the Chicago
mailing list