You are not logged in.

#1 2005-10-24 22:08:41

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

python's popen2

Ok, here's a contrived example:

import popen2
import sys, os

class bgprocess:
   def __init__(self,cmdline):
      self.pipe = popen2.Popen4(cmdline)

   def __del__(self):
      self.pipe.fromchild.close()
      self.pipe.tochild.close()

   def send(self,txt):
      self.pipe.tochild.write(txt)
      self.pipe.tochild.flush()

   def recv(self):
      return self.pipe.fromchild.read()


b = bgprocess("cat")
b.send("hellon")
print "printing: " + b.recv()

If you run "cat" at the command line, it simple echos back what you type when you hit enter.  I want to interface with this (as an example only).

However, the above hangs.  If you were to replace the flush() call in bgprocess.send, with "close()" then everything works perfectly.  Problem is, I just closed my stdin for the childprocess.  If I wanted to repeatedly use this as a "command handler", it wouldn't work.

Does anyone know away around this?  It seems to work fine until the background proces is interactive.

Offline

#2 2005-10-24 23:11:59

alterkacker
Member
From: Peoples Republic of Boulder
Registered: 2005-01-08
Posts: 52

Re: python's popen2

You can do the following:

    def send(self,txt): 
       self.pipe.tochild.write("%4d" % len(txt))
       self.pipe.tochild.write(txt) 
       self.pipe.tochild.flush() 
 
    def recv(self): 
       l = self.pipe.fromchild.read(4)
       lv = int(l)
       return self.pipe.fromchild.read(lv) 

But I admit I'm not sure why your original code doesn't work. Must be something weird with the buffering of the pipe object.

Offline

#3 2005-10-24 23:33:49

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: python's popen2

alterkacker wrote:

You can do the following:

    def send(self,txt): 
       self.pipe.tochild.write("%4d" % len(txt))
       self.pipe.tochild.write(txt) 
       self.pipe.tochild.flush() 
 
    def recv(self): 
       l = self.pipe.fromchild.read(4)
       lv = int(l)
       return self.pipe.fromchild.read(lv) 

But I admit I'm not sure why your original code doesn't work. Must be something weird with the buffering of the pipe object.

OMG! You rock - I would not have even thought of doing that.  I thought it was cat that was just sitting there doing nothing, I guess i never realized that it may have been the read()'s fault.

Offline

#4 2005-10-25 17:50:03

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: python's popen2

Ok, here's the thing.  This works great if I can prefix an int, but using read(1) over and over seems to work fine, until it gets to that last character and hangs.  It seems there is no way to make these things non-blocking, so, I'm going to drop popen and use 2 fifos (os.mkfifo), redirecting a fork()ed process's stdin/stdout there.  That should work perfectly.

Offline

#5 2005-10-25 22:16:00

alterkacker
Member
From: Peoples Republic of Boulder
Registered: 2005-01-08
Posts: 52

Re: python's popen2

Post back as to how the fifos work for you. I actually came up with my length prefix approach when I was working with fifos on an AIX box & had buffering problems similar to yours. But AIX is a strange beast.

Offline

Board footer

Powered by FluxBB