read stdout/stderr without blocking

Adriaan Renting renting at astron.nl
Wed Sep 14 03:59:43 EDT 2005


 
 
>>>Jacek Pop*awski <jpopl at interia.pl> 09/13/05 9:23 am >>> 
Grant Edwards wrote: 
>On 2005-09-12, Jacek Pop?awski <jpopl at interia.pl> wrote: 
> 
>>>       ready = select.select(tocheck, [], [], 0.25) ##continues after 0.25s 
>>>       for file in ready[0]: 
>>>           try: 
>>>               text = os.read(file, 1024) 
>> 
>>How do you know here, that you should read 1024 characters? 
>>What will happen when output is shorter? 
> 
> 
>It will return however much data is available. 
| 
|My tests showed, that it will block. 
|

IIRC it only blocks if there's nothing to read, that's why the select.select is done, which has a 0.25s timeout.
Please also note the fcntl.fcntl(self._child_fd, fcntl.F_SETFL, os.O_NONBLOCK) I do in the beginning of my code.

I basically stole this system from subProcess and Pexpect, both use the same mechanic. I just mashed those two together so I can read stdout and stderr separately in (near) real time, and reply to questions the external process asks me (like password prompts). It works on Linux with Python 2.3.4, the OP seems to use a different platform so YMMV. You can poll instead of select I think, but probably also only on Unix, this is from an earlier version of my code:

##            self.poll.register(self._child_fd)
##            self.poll.register(self._errorpipe_end)
...
##        if self._fd_eof and self._pipe_eof:
##            return 0
##        ready = self.poll.poll(250)
##        for x in ready:
##            text = ''
##            if (x[1] & select.POLLOUT) or (x[1] & select.POLLPRI):
##                try:
##                    text = os.read(x[0], 1024)
##                except:
##                    if x[0] == self._child_fd:
##                        self._fd_eof   = 1
##                    elif x[0] == self._errorpipe_end:
##                        self._pipe_eof = 1
##            if (x[1] & select.POLLNVAL) or (x[1] & select.POLLHUP) or (x[1] & select.POLLERR) or (text == ''):
##                if x[0] == self._child_fd:
##                    self._fd_eof   = 1
##                elif x[0] == self._errorpipe_end:
##                    self._pipe_eof = 1
##            elif text:
...
##        self.poll.unregister(self._child_fd)
##        self.poll.unregister(self._errorpipe_end)

 
-- 
http://mail.python.org/mailman/listinfo/python-list 




More information about the Python-list mailing list