请注意,内部
file.readlines([size])循环
read()多次调用syscall并尝试填充的内部缓冲区
size。第一次调用
read()将立即返回,因为select()表示fd可读。但是,第二个调用将阻塞,直到有可用数据为止,这违背了使用select的目的。无论如何,
file.readlines([size])在异步应用程序中使用都是棘手的。
您应该
os.read(fd, size)为每个通过选择的每个fd调用一次。这将执行无阻塞读取,并允许您缓冲部分行,直到数据可用并明确检测到EOF。
我修改了您的代码以说明使用
os.read。它还从过程中读取
stderr:
import osimport selectimport subprocessfrom cStringIO import StringIOtarget = 'Engine'PIPE = subprocess.PIPEengine = subprocess.Popen(target, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE)engine.stdin.write(b"gon")engine.stdin.flush()class LineReader(object): def __init__(self, fd): self._fd = fd self._buf = '' def fileno(self): return self._fd def readlines(self): data = os.read(self._fd, 4096) if not data: # EOF return None self._buf += data if 'n' not in data: return [] tmp = self._buf.split('n') lines, self._buf = tmp[:-1], tmp[-1] return linesproc_stdout = LineReader(engine.stdout.fileno())proc_stderr = LineReader(engine.stderr.fileno())readable = [proc_stdout, proc_stderr]while readable: ready = select.select(readable, [], [], 10.0)[0] if not ready: continue for stream in ready: lines = stream.readlines() if lines is None: # got EOF on this stream readable.remove(stream) continue for line in lines: print line


