当有数据可用时,我想打开几个子进程并从他们的stdin / stdout读/写。
首先尝试:
import subprocess, select, fcntl, os
p1 = subprocess.Popen("some command", stdout=subprocess.PIPE)
p2 = subprocess.Popen("another command", stdout=subprocess.PIPE)
def make_nonblocking(fd):
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
make_nonblocking(p1.stdout)
make_nonblocking(p2.stdout)
size = 10000
while True:
inputready, outputready, exceptready = select.select([ p1.stdout.fileno(), p2.stdout.fileno() ],[],[])
for fd in inputready:
if fd == p1.stdout.fileno():
data = p1.stdout.read(size)
print "p1 read %d" % (len(data))
elif fd == p2.stdout.fileno():
data = p2.stdout.read(size)
print "p2 read %d" % (len(data))
这种工作方式。使文件描述符无阻塞使得小于完整大小的读取成功,这很好。通过fileno查找流是丑陋但有效(最好有一个字典)。错误处理不是很正确,任何退出的命令都会导致“IOError:[Errno 32] Broken pipe”(不知道在哪里:它被报告为在其中一个打印语句中,这是伪造的)。
将此扩展到写入也有一些问题。理论上,将PIPE_BUF字节写入一个文件描述符,该文件描述符已经准备好从select中写入了。这也很有效,但是需要以某种方式改组数据缓冲区以允许从读取的内容中写入不同大小的块(或者可能具有固定大小的环形缓冲区并且如果我们要缓冲更多则停止读取)。
有更简洁的方法来实现这一目标吗?也许线程,或者一些类似AIO的调用来检查可以无阻塞地读/写多少,或者....
任何人都可以提供一个从一个子进程读取并异步写入另一个子进程的工作示例吗?