Python已经实现了communicate()
方法(它可以去到A.py
,B.py
也可以)。然而,它只适用于简单通信(你知道前面要发送的数据是什么),如果你需要一个更复杂的通信,比如:
send data to process B
read stdout
if stdout ...
do something bases on stdout
write to stdin
你需要实现自己的communicate()
,原始实现在这里。
逐步操作
我已经逐步测试和调试过这个内容,以下是发生的情况:
A: process.stdin.write(b'hello\r\n')
B: line = sys.stdin.readline()
所以在添加了
bufsize=0
(无缓冲)之后
A: process.stdin.write(b'hello\r\n')
B: line = sys.stdin.readline()
B: print('Send back', line.strip())
A: process.stdout.readline()
那么什么有效?
A: process.stdin.write(b'hello\r\n')
B: line = sys.stdin.readline()
B: print('Send back', line.strip())
B: sys.stdout.flush()
A: process.stdout.readline()
解释
您已将缓冲区设置为io.DEFAULT_BUFFER_SIZE
(通常为4090B)。来自文档:
bufsize将作为创建stdin / stdout / stderr管道文件对象时io.open()函数的相应参数提供:0表示无缓冲(读取和写入是一个系统调用,并且可以返回短),1表示行缓冲,任何其他正数值表示使用大约该大小的缓冲区。负的bufsize(默认值)意味着将使用io.DEFAULT_BUFFER_SIZE的系统默认值。
因此,首先A
不会刷新,因为它尚未填满其缓冲区,因此B
正在等待。在Windows下,不能简单地使用process.stdin.flush()
,因此必须使用bufsize = 0
。
同样,编写os.linesep
(\r\n
)也很重要,因为它涉及到readline()
。
注意:我认为使用bufsize=1
(行缓冲)也应该可以工作,但事实并非如此。我不知道为什么。
然后在B
中当它不刷新sys.stdout
时,相同的情况发生了,让我感到惊讶的是,B:sys.stdout
没有被设置为无缓冲,因为:
bufsize将作为相应的参数提供给io.open()函数,在创建stdin/stdout/stderr管道文件对象时使用。
无论如何,你必须在B
中调用sys.stdout.flush()
。
它可以通过close()
工作,因为它强制执行flush()
。
给我代码
A.py:
import subprocess
import sys
process = subprocess.Popen([sys.executable, r'B.py'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE, bufsize=0)
for _ in range(3):
process.stdin.write(b'hello\r\n')
print(process.stdout.readline())
B.py:
import sys
for line in sys.stdin:
print('Send back', line.strip())
sys.stdout.flush()
Python 3.2.5 (default, May 15 2013, 23:07:10) [MSC v.1500 64 bit (AMD64)] on win32
,使用的是Windows 7系统,可能与版本有关。我觉得让这些东西正常工作有点神奇。 - Vyktor