Wrapping A Shell

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jeremy Moles

    #1

    Wrapping A Shell

    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?

  • tleeuwenburg@gmail.com

    #2
    Re: Wrapping A Shell


    Jeremy Moles wrote:
    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

    Comment

    • Nick Craig-Wood

      #3
      Re: Wrapping A Shell

      Jeremy Moles <jeremy@emperor linux.comwrote:
      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

      Download Pexpect - Pure Python Expect-like module for free. Pexpect is a Python module for spawning child applications; controlling them;


      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.filen o(), 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(1 024)
      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)

      --
      Nick Craig-Wood <nick@craig-wood.com-- http://www.craig-wood.com/nick

      Comment

      Working...