Python 如何异步读取和写入子进程?

Python 如何异步读取和写入子进程?,python,asynchronous,io,subprocess,fork,Python,Asynchronous,Io,Subprocess,Fork,当有数据可用时,我想打开几个子进程并从它们的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 = f

当有数据可用时,我想打开几个子进程并从它们的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查找流很难看,但很有效(最好有一个dict)。不过,错误处理并不完全正确,任何退出的命令都会导致“IOError:[Errno 32]管道破裂”(不确定在何处:它被报告为在某个print语句中,这是伪造的)

将其扩展到写操作也有一些问题。理论上,将PIPE_BUF字节写入从select返回的准备写入的文件描述符应该可以。这也是一种工作方式,但需要以某种方式洗牌数据缓冲区,以允许写入与读取内容不同大小的块(或者可能具有固定大小的环形缓冲区,并且如果我们要缓冲更多的数据,则停止读取)

有没有更干净的方法来实现这一点?可能是线程,或者一些类似AIO的调用来检查在没有阻塞的情况下可以读/写多少,或者


有谁能给出一个从一个子进程读取数据并异步写入另一个子进程的工作示例吗?

下面是一个示例。你能用stdin=p.stdout吗?请看链接和我的答案@J.F.Sebastian:线程化示例非常棒!另一个示例probalby不适用于我,它的结构似乎类似于“process.communicate()[0].splitlines()”将整个输出读取到内存中,即使使用asyncio也是如此。它将所有输出读取到内存中,因为这是OP想要的。如果您不需要它,那么可以使用
process.stdout.readline()
(逐行读取)或
.read(n)
读取不超过
n
字节。