readline() blocks after select() says there's data??

wealthychef wealthychef at mac.com
Thu Mar 14 22:34:42 EST 2002


Hi, I'm pretty clueless about sockets, but here's my problem.  Please
help!

I have a process (actually a 'make') which takes a long time to
complete and periodically spits out lines of information.  I want to
keep an eye on it, echo what it says as it says it, and report its
status when done.  So I wrote a function called "WaitForCommand",
which in turn periodically calls CheckForOutput() to see if there's
anything to get.

My code is below.  The relevant lines are the following:

        selectables = [theProcess.childerr, theProcess.fromchild]
        (input, output, exc) = select.select([],selectables,
selectables)
        if output:
             for theOutput in output:
                if theOutput == theProcess.childerr:
                    eoutput = theProcess.childerr.readline(bufsize)
                    print eoutput
                elif theOutput == theProcess.fromchild:
                    stdoutput = theProcess.fromchild.readline(bufsize)
                    print stdoutput

It blocks forever waiting for theProcess.childerr.readline(bufsize) to
return.  I expect it to block waiting for select.select(); that would
not be a problem.  The problem is that select is claiming there's
stuff to be read, then when I try to read it, it's not there!  How can
that be?  I don't want to block forever waiting for childerr when
fromchild has something for me;  that's why I am using select, to be
able to see what's ready, right?  I don't get it.

******************************************************
Here is the full code if that's useful.  Please trim this out of your
replies if not needed.  This message is heinously long as it is.

def CheckForOutput(theProcess, selectables, bufsize, NoStdErr,
Verbose):
   while 1:
        (input, output, exc) = ([],[],[])
        (input, output, exc) =
select.select([],selectables,selectables)
        if output:
             for theOutput in output:
                if theOutput == theProcess.childerr:
                    eoutput = theProcess.childerr.readline(bufsize)
                    print eoutput
                elif theOutput == theProcess.fromchild:
                    stdoutput = theProcess.fromchild.readline(bufsize)
                    print stdoutput
         if exc:
             pollNum = theProcess.poll()
            if pollNum != -1:
                print "process closed"
                break
            raise ("WaitForCommand-- Unknown Error from process
pipe.")
        if not output and not exc:
            break
    return    

def WaitForCommand(iCommand, NoStdErr=None, RaiseExceptionOnErr=None,
Verbose=None, bufsize=-1):
     theProcess = popen2.Popen3(iCommand,capturestderr=1,
bufsize=bufsize)
    selectables = [theProcess.childerr, theProcess.fromchild]
    while 1:
        CheckForOutput(theProcess, selectables, bufsize, NoStdErr,
Verbose)
        returnCode = theProcess.poll()            
        if returnCode != -1:
            CheckForOutput(theProcess, selectables, bufsize, NoStdErr,
Verbose)
            if returnCode and RaiseExceptionOnErr:
                raise 'Error: return code is ' + str(returnCode)
            if Verbose:
                print 'return code is ', returnCode
            break
    return



More information about the Python-list mailing list