Getting stdout and stderr from popen
Jonathan Gardner
jgardn at alumni.washington.edu
Wed Mar 6 09:09:51 EST 2002
Stefan Heimann scribbled with his keyboard:
> I want to launch an external process and have stdout and stderr
> redirected to one output stream,
You are on Unix, right?
> something like
>
> f = os.popen('cvs status 2>&1')
>
> does the right thing, but does not work on all platforms.
>
> If I write
>
> pin, pout, perr = os.popen3('cvs status')
>
> I get the output of stderr and stdout but not in the right order.
What do you mean in the right order? Do you mean that it is returning in,
err, out or that err and out are spitting out stuff simultaneously?
>
> I tried also
>
> sys.stderr = sys.stdout
> f = os.popen('cvs status')
> f.read()
>
> but still I get only the output from stdout (what cvs outputs on
> stderr is written directly to the console).
>
Okay, let's talk about what is really happening deep underneath the hood.
These popen functions are a shorthand for a very common thing in the world
of Unix. It goes something like this:
1) make three pipes (in, out, err)
2) fork.
3) If you are the child (pid == 0) then close the writing part of in, and
the reading part of out and err.
4) Now, make in be my stdin, out my stdout, err my stderr. (this has to be
done at a lower level - you need to use the dup type functions.)
5) Now, execute the program I wanted to execute ("cvs status") and exit
when it is finished. "cvs status" should be reading from and writing to the
pipes.
3) If you are the parent (pid != 0, pid is the child's pid) then close the
reading part of in, the writing part of out and err. If you want to send
something to the child's stdin, write to in. If you want to see what he is
saying, read from out. If you want to hear what he is crying about, read
from err. (Yes, I meant to write (3).)
4) go on with your parental role and discipline your child if he misbehaves.
That is what is happening under the hood. There are four things the parent
gets when he makes a child like this - in, out, err, and the pid.
os.popen plays a funny trick. He only gives us back one file that we can
either read from or write to. You have to choose one. If you choose the
write to file, then you are going to be writing to the child's stdin. If
you choose the read from one, then you will be reading from his stdout. You
can't read from stderr from this one. It will use stderr from the parent.
(Note: this may be different from sys.stderr.)
os.popen2, 3, and 4 do something similar, but they will give you back
multiple pipes. Read the documentation closely.
My favorite, for when I am a control freak, is the Popen2, 3, or 4 class in
popen2 module. Take a look at that for how that works.
More questions about pipes and child processes? Take it to a Unix
programmer. Windows does a horrible job with it, and Windows programmers
tend to only know about it, but are not able to do much with it.
Jonathan
More information about the Python-list
mailing list