10.1.4 与其他命令交互
前面的所有例子都假设交互量是有限的。communicate()方法读取所有输出,返回之前要等待子进程退出。也可以在程序运行时从Popen实例使用的各个管道句柄增量地进行读写。可以用一个简单的应答程序来展示这个技术,这个程序从标准输入读,并写至标准输出。
下一个例子中使用脚本repeater.py作为子进程。它从stdin读取,并将值写至stdout,一次处理一行,知道再没有更多输入为止。开始和停止时它还会向stderr写一个消息,显示子进程的生命期。
# repeater.py
import sys
sys.stderr.write('repeater.py: starting\n')
sys.stderr.flush()
while True:
next_line = sys.stdin.readline()
sys.stderr.flush()
if not next_line:
break
sys.stdout.write(next_line)
sys.stdout.flush()
sys.stderr.write('repreter.py: exiting\n')
sys.stderr.flush()
下一个交互例子将采用不同方式使用Popen实例的stdin和stdout文件句柄。在第一个例子中,将把一组5个数写至进程的stdin,每写一个数就读回下一行输出。第二个例子中仍然写同样的5个数,但要使用communicate()一次读取全部输出。
import io
import subprocess
print('One line at a time:')
proc = subprocess.Popen(
'python3 repeater.py',
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
stdin = io.TextIOWrapper(
proc.stdin,
encoding='utf-8',
line_buffering=True, # Send data on newline
)
stdout = io.TextIOWrapper(
proc.stdout,
encoding='utf-8',
)
for i in range(5):
line = '{}\n'.format(i)
stdin.write(line)
output = stdout.readline()
print(output.rstrip())
remainder = proc.communicate()[0].decode('utf-8')
print(remainder)
print()
print('All output at once:')
proc = subprocess.Popen(
'python3 repeater.py',
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
stdin = io.TextIOWrapper(
proc.stdin,
encoding='utf-8',
)
for i in range(5):
line = '{}\n'.format(i)
stdin.write(line)
stdin.flush()
output = proc.communicate()[0].decode('utf-8')
print(output)
对于这两种不同的循环,“repeater.py:exiting”行出现在输出的不同位置上。
运行结果: