实时读取/写入子进程的stdin/stdout
我想为另一个命令行程序做一个Python的封装。
我的目标是尽可能快地读取Python的 stdin
(标准输入),对它进行过滤和转换,然后迅速写入到子程序的 stdin
。
同时,我也想尽量快地从子程序的 stdout
(标准输出)读取数据,经过一些处理后,迅速写入到Python的 stdout
。
Python的子进程模块有很多警告,建议使用 communicate()
来避免死锁问题。但是,使用 communicate()
的话,我要等子程序结束后才能访问它的 stdout
。
2 个回答
1
免责声明:这个解决方案可能需要你能访问到你想要调用的进程的源代码,但即使如此,尝试一下也许是值得的。这取决于被调用的进程是否定期清空它的 stdout
缓冲区,而这并不是标准做法。
假设你有一个通过 subprocess.Popen
创建的进程 proc
。这个 proc
有两个属性,分别是 stdin
和 stdout
。这些属性其实就是像文件一样的对象。所以,要通过 stdin
发送信息,你可以调用 proc.stdin.write()
。要从 proc.stdout
获取信息,你可以调用 proc.stdout.readline()
来读取一行内容。
几点注意事项:
- 当你通过
write()
向proc.stdin
写入内容时,记得在输入的最后加一个换行符。如果没有换行符,你的子进程会一直卡在那里,直到你输入一个换行符。 - 要从
proc.stdout
读取信息,你需要确保子进程调用的命令在每次打印后都能正确清空它的 stdout 缓冲区,并且每一行的末尾都有换行符。如果 stdout 缓冲区没有在合适的时机被清空,你调用proc.stdout.readline()
时也会卡住。
1
我觉得你可以小心地忽略那些警告,自己使用 Popen.stdin
等等。只要确保逐行处理这些数据流,并且合理安排处理的时间,这样就不会让任何缓冲区满了。在Python中,有一种相对简单(但效率不高)的方法,就是为这三个数据流使用不同的线程。这就是 Popen.communicate
在内部处理的方式。你可以看看它的源代码,了解具体是怎么做的。