read stdout/stderr without blocking
Adriaan Renting
renting at astron.nl
Mon Sep 12 07:57:39 EDT 2005
I was not aware you were using Windows, you might need to find something similar to select and pty that works in Windows or maybe go though Cygwin, I don't know. I'm on Linux, the only help I can offer is showing you my working code, that's a mix of Pexpect, subProcess and Parseltongue.
I'm not sure if this is 100% correct, it just happens to work and might help you in solving a similar problem:
---- in spawn()
(self._errorpipe_end, self._errorpipe_front) = os.pipe() ## need to handle stderr separate from stdout
try:
(self._pid, self._child_fd) = pty.fork()
except OSError, e:
raise Exception ('fork failed')
if self._pid == 0: ## the new client
try:
os.dup2(self._errorpipe_front, 2) ## we hardcoded assume stderr of the pty has fd 2
os.close(self._errorpipe_end)
os.close(self._errorpipe_front) ## close what we don't need
os.execvp(self.task, self.inputs)
except:
sys.stderr.write('Process could not be started: ' + self.task)
os._exit(1)
else: ## the parent
os.close(self._errorpipe_front) ## close what we don't need
fcntl.fcntl(self._child_fd, fcntl.F_SETFL, os.O_NONBLOCK)
---- in handle_messages()
tocheck=[]
if not self._fd_eof:
tocheck.append(self._child_fd)
if not self._pipe_eof:
tocheck.append(self._errorpipe_end)
ready = select.select(tocheck, [], [], 0.25) ##continues after 0.25s
for file in ready[0]:
try:
text = os.read(file, 1024)
except: ## probalby Input/Output error because the child died
text = ''
if text:
for x in self._expect:
if x[0] in text: ## we need to do something if we see this text
returntext = x[1](text)
if returntext:
os.write(file, returntext)
self.handle_text(text)
else:
if file == self._child_fd:
self._fd_eof = 1
elif file == self._errorpipe_end:
self._pipe_eof = 1
return 1
if self._fd_eof or self._pipe_eof: # should be an and not an or, but python 2.3.5 doesn't like it
return 0
if len(ready[0]) == 0: ## no data in 0.25 second timeout
return 1
return 0
---- in finish()
(pid, status) = os.waitpid(self._pid, os.WNOHANG) ## clean up the zombie
assert(pid == self._pid)
if os.WIFEXITED(status) or os.WIFSIGNALED(status):
self._pid = 0
self.exitstatus = status
assert(self.finished())
del self._pid
os.close(self._child_fd)
os.close(self._errorpipe_end)
|>>>Jacek Pop*awski <jpopl at interia.pl> 09/12/05 1:14 pm >>>
|Adriaan Renting wrote:
|>Check out the select module, for an example on how to use it:
|>pexpect.sourceforge.net
|
|Two problems:
|- it won't work on Windows (Cygwin)
|- how much data should I read after select? 1 character? Can it block if
|I read 2 characters?
|--
|http://mail.python.org/mailman/listinfo/python-list
More information about the Python-list
mailing list