os.popen2

Donn Cave donn at u.washington.edu
Mon Feb 5 16:44:51 EST 2001


Quoth Venkatesh Prasad Ranganath <rvprasad at cis.ksu.edu>:
| Hi,
|
| The following code stalls
|
| import os
| i = os.popen2("/bin/bash")
| i[0].write("ls -lR")
| i[1].read()
| -----------stalls here
|
| Am I missing something the way it should behave or isn't it possible to execute
| a process using popenX, keep it alive and interact with it?

Yes, you're missing a couple of things, yes, you can interact with bash
this way, no, you can't interact this way with just any process.

To get a better sense of what's going on in your program, it might help
you to use a shell command that has some effect besides output to the
other pipe.  For example, have it write to a file - instead of 'ls -lR',
for example, try 'ls -lR > xxx' (or 'date > xxx', you really don't need
much output to start with.)  Now you can see specifically whether the
shell command executed, before you waste a lot of time asking why you
don't see its output.  You can also use "ps" to see whether the shell
process is still alive and waiting for something.

Now the first thing you need for your shell command lines is a trailing
newline:  'ls -lR\n', just like any file.  The shell doesn't execute
a command until it has read it, and it hasn't finished reading it until
it encounters the trailing newline.  Next, you have to actually write
the command line to the pipe, from the C library stdio buffer it's
sitting in now  - i[0].flush().  

At this point, I expect you will see evidence that the command actually
ran, and you should now change your command back to write to output -
but you still won't have any output.  This is because i[1].read()
is trying to read up everything, and the pipe is still open so there
could be more coming.  Another C library notion.  I personally would
just ditch the file object / C stdio stuff and use the UNIX file
descriptor directly - see fileobject fileno(), posix read() and write().

All right, now if you have been able to fix all this up, you should
be able to write and read one shell command after another.  It may
be a bit tricky to figure out how much output to expect from a shell
command, and when it's finished and ready for the next command, but
you can probably figure something out.  But if you take bash out of
there and replace it with almost any other application, you'll find
that you're back where you started, because most of these applications
use the same C library output and they're back there at step 1.b.,
without any way to get them to flush their buffer.

If there's any solution at all, it's to use a "pty" device instead
of pipes.  The pty library module has support for that, especially
in Python 2.0 and on the more common platforms.  The pty master fd
you get back will be a UNIX file descriptor that handles both reading
and writing.

	Donn Cave, donn at u.washington.edu



More information about the Python-list mailing list