您不需要在示例中使用process.communicate。在
只需使用process.stdin.write和process.stdout.read进行读写。还要确保发送一个新行,否则read不会返回。当您从stdin读取时,还必须处理来自echo的新行。在
注意:process.stdout.read将阻塞,直到EOF。在# talk_with_example_input.py
import subprocess
process = subprocess.Popen(["./exampleInput.sh"],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE)
process.stdin.write("5\n")
stdout = process.stdout.readline()
print(stdout)
if stdout == "25\n":
process.stdin.write("yes\n")
print(process.stdout.readline())
^{pr2}$
更新
以这种方式与程序通信时,必须特别注意应用程序实际编写的内容。最好是在十六进制编辑器中分析输出:$ chimera nogui 2>&1 | hexdump -C
请注意,readline[1]只读取下一个换行符(\n)。在您的例子中,您必须至少调用readline四次才能得到第一块输出。在
如果您只想在子进程停止打印之前读取所有内容,则必须逐字节读取并实现超时。遗憾的是,read和{}都没有提供这种超时机制。这可能是因为底层的readsyscall[2](Linux)也没有提供一个。在
在Linux上,我们可以使用poll / select编写单线程read_with_timeout()。有关示例,请参见[3]。在from select import epoll, EPOLLIN
def read_with_timeout(fd, timeout__s):
"""Reads from fd until there is no new data for at least timeout__s seconds.
This only works on linux > 2.5.44.
"""
buf = []
e = epoll()
e.register(fd, EPOLLIN)
while True:
ret = e.poll(timeout__s)
if not ret or ret[0][1] is not EPOLLIN:
break
buf.append(
fd.read(1)
)
return ''.join(buf)
如果您需要一种可靠的方法来读取Windows和Linux下的非阻塞,this answer might be helpful。在readline(limit=-1)
Read and return one line from the stream. If limit is specified, at most limit bytes will be read.
The line terminator is always b'\n' for binary files; for text files, the newline argument to open() can be used to select the line terminator(s) recognized.
[2]来自man 2 read:#include
ssize_t read(int fd, void *buf, size_t count);
[3]示例$ tree
.
├── prog.py
└── prog.sh
在程序sh在#!/usr/bin/env bash
for i in $(seq 3); do
echo "${RANDOM}"
sleep 1
done
sleep 3
echo "${RANDOM}"
在进度计划在# talk_with_example_input.py
import subprocess
from select import epoll, EPOLLIN
def read_with_timeout(fd, timeout__s):
"""Reads from f until there is no new data for at least timeout__s seconds.
This only works on linux > 2.5.44.
"""
buf = []
e = epoll()
e.register(fd, EPOLLIN)
while True:
ret = e.poll(timeout__s)
if not ret or ret[0][1] is not EPOLLIN:
break
buf.append(
fd.read(1)
)
return ''.join(buf)
process = subprocess.Popen(
["./prog.sh"],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE
)
print(read_with_timeout(process.stdout, 1.5))
print(' -')
print(read_with_timeout(process.stdout, 3))$ python2 prog.py
6194
14508
11293
-
10506