使用
fcntl.fcntl使管道无阻塞,并使用
select.select等待数据在任一管道中可用.例如:
# Helper function to add the O_NONBLOCK flag to a file descriptor
def make_async(fd):
fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
# Helper function to read some data from a file descriptor, ignoring EAGAIN errors
def read_async(fd):
try:
return fd.read()
except IOError, e:
if e.errno != errno.EAGAIN:
raise e
else:
return ''
process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
make_async(process.stdout)
make_async(process.stderr)
stdout = str()
stderr = str()
returnCode = None
while True:
# Wait for data to become available
select.select([process.stdout, process.stderr], [], [])
# Try reading some data from each
stdoutPiece = read_async(process.stdout)
stderrPiece = read_async(process.stderr)
if stdoutPiece:
print stdoutPiece,
if stderrPiece:
print stderrPiece,
stdout += stdoutPiece
stderr += stderrPiece
returnCode = process.poll()
if returnCode != None:
return (returnCode, stdout, stderr)
请注意,fcntl仅适用于类似Unix的平台,包括Cygwin.
如果你需要它在没有Cygwin的Windows上工作,它是可行的,但它更加困难.你必须:
>使用pywin32库调用本机Win32 API
>使用SetNamedPipeHandleState和PIPE_NOWAIT使stdout和stderr管道无阻塞
>使用WaitForMultipleObjects而不是选择等待数据变为可用
>使用ReadFile读取数据