Running a program from another program.

Laurent Verweijen somelauw at gmail.com
Fri Jun 18 11:47:52 EDT 2010


Op donderdag 17-06-2010 om 15:16 uur [tijdzone -0700], schreef Stephen
Hansen: 
> On 6/17/10 3:06 PM, Laurent Verweijen wrote:
> >>
> >> In your other thread you include an actual traceback:
> >>
> >> Traceback (most recent call last):
> >>   File "subchronous_test.py", line 5, in <module>
> >>     send_all(str(p), n)
> >>   File "/home/Somelauw/asynchronous.py", line 145, in send_all
> >>     while len(data):
> >> TypeError: object of type 'int' has no len()
> >>
> >> The first argumetn to send_all should be the actual Popen subclass. The
> >> second should be a string to send. I think that line really is intended
> >> to be:
> >>
> >> send_all(p, str(n)) # assuming 'n' is say, the number 5.
> >>
> > 
> > You are right, I swapped the parameters, but even if I correct it, it
> > still gives the second error.
> > 
> 
> General rule of thumb: its best to never use the word "still" when it
> comes to debugging Python and exceptions, unless you are absolutely
> certain the exception is precisely the same.
> 
> I don't doubt that you may still get an exception on send_all; but there
> is no way you're getting the *same* exception (that specific type error:
> attempting to call len() on an integer) if you corrected your arguments.
> 
> You're getting the EOFError, because you're never sending anything to
> the subprocess. You're not getting anything from the subprocess because
> it never receives anything to send back. And apparently there's an error
> on send, which is causing that problem, but that error is...?
>
My last post, contains the output after I fixed swapping the parameters
and everything you said.

I think there is still a problem with output that gets blocked.
Couldn't it be just that the output which gets blocked is causing this
error?

Anyway here is the output again:

python subchronous_test.py




Traceback (most recent call last):
  File "increment.py", line 8, in <module>
    n = int(raw_input(str(n))) + 1
EOFError: EOF when reading a line

close failed in file object destructor:
Error in sys.excepthook:

Original exception was:



And here are all 3 files concatenated:

# subchronous_test
import sys
from asynchronous import *
p = Popen(["python", "increment.py"], stdin=PIPE, stdout=PIPE, stderr =
sys.stderr)

for n in [5, 7, 10, 4]:
        send_all(p, str(n))
        print(recv_some(p))


# increment.py
import sys, traceback

try:
        n = 0
        while True:
                n = int(raw_input(str(n))) + 1
except:
        print >>sys.stderr, traceback.format_exc()


# asynchronous.py
## {{{ http://code.activestate.com/recipes/440554/ (r10)
import os
import subprocess
import errno
import time
import sys

PIPE = subprocess.PIPE

if subprocess.mswindows:
    from win32file import ReadFile, WriteFile
    from win32pipe import PeekNamedPipe
    import msvcrt
else:
    import select
    import fcntl

class Popen(subprocess.Popen):
    def recv(self, maxsize=None):
        return self._recv('stdout', maxsize)
    
    def recv_err(self, maxsize=None):
        return self._recv('stderr', maxsize)

    def send_recv(self, input='', maxsize=None):
        return self.send(input), self.recv(maxsize),
self.recv_err(maxsize)

    def get_conn_maxsize(self, which, maxsize):
        if maxsize is None:
            maxsize = 1024
        elif maxsize < 1:
            maxsize = 1
        return getattr(self, which), maxsize
    
    def _close(self, which):
        getattr(self, which).close()
        setattr(self, which, None)
    
    if subprocess.mswindows:
        def send(self, input):
            if not self.stdin:
                return None

            try:
                x = msvcrt.get_osfhandle(self.stdin.fileno())
                (errCode, written) = WriteFile(x, input)
            except ValueError:
                return self._close('stdin')
            except (subprocess.pywintypes.error, Exception), why:
                if why[0] in (109, errno.ESHUTDOWN):
                    return self._close('stdin')
                raise

            return written

        def _recv(self, which, maxsize):
            conn, maxsize = self.get_conn_maxsize(which, maxsize)
            if conn is None:
                return None
            
            try:
                x = msvcrt.get_osfhandle(conn.fileno())
                (read, nAvail, nMessage) = PeekNamedPipe(x, 0)
                if maxsize < nAvail:
                    nAvail = maxsize
                if nAvail > 0:
                    (errCode, read) = ReadFile(x, nAvail, None)
            except ValueError:
                return self._close(which)
            except (subprocess.pywintypes.error, Exception), why:
                if why[0] in (109, errno.ESHUTDOWN):
                    return self._close(which)
                raise
            
            if self.universal_newlines:
                read = self._translate_newlines(read)
            return read

    else:
        def send(self, input):
            if not self.stdin:
                return None

            if not select.select([], [self.stdin], [], 0)[1]:
                return 0

            try:
                written = os.write(self.stdin.fileno(), input)
            except OSError, why:
                if why[0] == errno.EPIPE: #broken pipe
                    return self._close('stdin')
                raise

            return written

        def _recv(self, which, maxsize):
            conn, maxsize = self.get_conn_maxsize(which, maxsize)
            if conn is None:
                return None
            
            flags = fcntl.fcntl(conn, fcntl.F_GETFL)
            if not conn.closed:
                fcntl.fcntl(conn, fcntl.F_SETFL, flags| os.O_NONBLOCK)
            
            try:
                if not select.select([conn], [], [], 0)[0]:
                    return ''
                
                r = conn.read(maxsize)
                if not r:
                    return self._close(which)
    
                if self.universal_newlines:
                    r = self._translate_newlines(r)
                return r
            finally:
                if not conn.closed:
                    fcntl.fcntl(conn, fcntl.F_SETFL, flags)

message = "Other end disconnected!"

def recv_some(p, t=.1, e=1, tr=5, stderr=0):
    if tr < 1:
        tr = 1
    x = time.time()+t
    y = []
    r = ''
    pr = p.recv
    if stderr:
        pr = p.recv_err
    while time.time() < x or r:
        r = pr()
        if r is None:
            if e:
                raise Exception(message)
            else:
                break
        elif r:
            y.append(r)
        else:
            time.sleep(max((x-time.time())/tr, 0))
    return ''.join(y)
    
def send_all(p, data):
    while len(data):
        sent = p.send(data)
        if sent is None:
            raise Exception(message)
        data = buffer(data, sent)

if __name__ == '__main__':
    if sys.platform == 'win32':
        shell, commands, tail = ('cmd', ('dir /w', 'echo HELLO WORLD'),
'\r\n')
    else:
        shell, commands, tail = ('sh', ('ls', 'echo HELLO WORLD'), '\n')
    
    a = Popen(shell, stdin=PIPE, stdout=PIPE)
    print recv_some(a),
    for cmd in commands:
        send_all(a, cmd + tail)
        print recv_some(a),
    send_all(a, 'exit' + tail)
    print recv_some(a, e=0)
    a.wait()
## end of http://code.activestate.com/recipes/440554/ }}}





More information about the Python-list mailing list