import popen2 import threading import time import os timeout = 10 def openPipe(command): '''We need to use the asynchronous version here since we want to avoid blocking reads''' pipe = popen2.Popen3(command, 1) input = pipe.tochild output = pipe.fromchild err = pipe.childerr return (input, output, err, pipe) def runShellCommand(command): import select ret = None out = '' err = '' count = 0 (input, output, error, pipe) = openPipe(command) input.close() lst = [output, error] while lst: ready = select.select(lst, [], []) count = count + 1 # somehow this line triggers the bug more frequently if len(ready[0]): if error in ready[0]: msg = error.readline() if msg: err += msg else: lst.remove(error) if output in ready[0]: msg = output.readline() if msg: out += msg else: lst.remove(output) output.close() error.close() if pipe: ret = pipe.wait() if ret: print 'pipe.wait() returns error code:', ret return (out, err, ret) ##################################################### def runThreadShellCommand(command): thread = threading.Thread(target = runShellCommand, name = 'Shell Command', args = (command,)) thread.setDaemon(1) thread.start() thread.join(timeout) return 0 time1 = time.time() for count in range(0,30): runThreadShellCommand('/bin/true') time2 = time.time() print 'thread+pipe overhead',time2-time1 time1 = time.time() for count in range(0,30): runShellCommand('/bin/true') time2 = time.time() print 'pipe overhead', time2-time1