Wrapping A Shell

J

Jeremy Moles

I'm not sure if this is really the right place to ask this question, but
since the implementation is in Python, I figured I'd give it a shot.

I want to "wrap" a shell process using popen inside of python program
rather than creating a new shell process for each line I process in the
app. For example, the code might look like:


std = stdin, stdout, stderr = os.popen3("bash")

print >> stdin, "ls"

print stdout.readline()

However, it appears my understanding of popen (or perhaps buffered IO)
is off somewhere, because this certainly doesn't work anything like I
expect it to (it hangs on stdout.readline).

Obviously the example above is very contrived, but eventually I'll be
using this in an OpenGL "terminal" widget. Am I approaching this the
wrong way?
 
T

tleeuwenburg

Jeremy said:
I'm not sure if this is really the right place to ask this question, but
since the implementation is in Python, I figured I'd give it a shot.

I want to "wrap" a shell process using popen inside of python program
rather than creating a new shell process for each line I process in the
app. For example, the code might look like:


std = stdin, stdout, stderr = os.popen3("bash")

print >> stdin, "ls"

print stdout.readline()

However, it appears my understanding of popen (or perhaps buffered IO)
is off somewhere, because this certainly doesn't work anything like I
expect it to (it hangs on stdout.readline).

Obviously the example above is very contrived, but eventually I'll be
using this in an OpenGL "terminal" widget. Am I approaching this the
wrong way?

Try flushing the bufffer for stdin.


Cheers,
-T
 
N

Nick Craig-Wood

Jeremy Moles said:
I'm not sure if this is really the right place to ask this question, but
since the implementation is in Python, I figured I'd give it a shot.

I want to "wrap" a shell process using popen inside of python program
rather than creating a new shell process for each line I process in the
app. For example, the code might look like:


std = stdin, stdout, stderr = os.popen3("bash")

print >> stdin, "ls"

print stdout.readline()

However, it appears my understanding of popen (or perhaps buffered IO)
is off somewhere, because this certainly doesn't work anything like I
expect it to (it hangs on stdout.readline).

Obviously the example above is very contrived, but eventually I'll be
using this in an OpenGL "terminal" widget. Am I approaching this the
wrong way?

Short answer: use pexpect

http://pexpect.sourceforge.net/

Long answer:

Firstly modern pythonistas use subprocess instead of os.popen*.

Secondly, buffering is going to cause you trouble and possible
deadlocks.

There are two ways to rid yourself of deadlock.

1) read and write from seperate threads / processes. This is the
traditional unix way

2) use non blocking IO

Here is a possible way to solve the problems with subprocess (unix
only) and non blocking IO.

However I suspect you really want to use pexpect for this job...

from os import O_NONBLOCK
from errno import EAGAIN
from subprocess import Popen, PIPE
from fcntl import fcntl, F_SETFL, F_GETFL
from time import time

p = Popen(["/bin/bash", "-i"], shell=False, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)

# Make output streams non blocking (unix only)
for fd in (p.stdout.fileno(), p.stderr.fileno()):
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK)

def read_output(p, timeout=1.0):
"""Read the output from the subprocess, with timeout"""
end_time = time() + timeout
output = ""
while time() < end_time:
try:
output += p.stdout.read(1024)
except IOError, e:
if e.errno != EAGAIN:
raise
return output

p.stdin.write("ls\n")
print read_output(p)
p.stdin.write("uname -a\n")
print read_output(p)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,270
Latest member
TopCryptoTwitterChannels_

Latest Threads

Top