仔细阅读documentation(强调我的):
Popen.communicate(input=None)
与进程交互:向标准输入发送数据。从标准输出读取数据并
stderr,直到到达文件结尾。等待进程终止。
可选的输入参数应该是一个要发送给孩子的字符串
进程,或无,如果不应该向孩子发送数据。
communicate() 返回一个元组 (stdoutdata, stderrdata)。
注意,如果你想向进程的标准输入发送数据,你需要
使用stdin=PIPE 创建 Popen 对象。同样,得到任何东西
除了结果元组中的 None 之外,您需要提供 stdout=PIPE
和/或stderr=PIPE。
因此,您没有向进程发送任何内容,而是一次读取 所有 stdout。
在您的情况下,您实际上不需要等待提示将数据发送到进程,因为流是异步工作的:进程只有在尝试读取其STDIN 时才会获取您的输入:
In [10]: p=subprocess.Popen(("bash", "-c","echo -n 'prompt: '; read -r data; echo $data"),stdin=subprocess.PIPE,stdout=subprocess.PIPE)
In [11]: p.communicate('foobar')
Out[11]: ('prompt: foobar\n', None)
如果您出于某种原因坚持等待提示(例如,您的进程也在提示之前检查输入,期待其他内容),you need to read STDOUT manually and be VERY careful how much you read:由于 Python 的 file.read 正在阻塞,一个简单的 read() 将死锁,因为它等待 EOF 并且子进程不会关闭 STDOUT - 因此不会产生 EOF - 直到它收到您的输入。如果输入或输出长度可能超过 stdio 的缓冲区长度(在您的特定情况下不太可能),you also need to do stdout reading and stdin writing in separate threads。
这是一个使用 pexpect 的示例,它可以为您解决这个问题(我使用 pexpect.fdexpect 而不是 pexpect.spawn suggested in the doc '因为它适用于所有平台):
In [1]: import pexpect.fdpexpect
In [8]: p=subprocess.Popen(("bash", "-c","echo -n 'prom'; sleep 5; echo 'pt: '; read -r data; echo $data"),stdin=subprocess.PIPE,stdout=subprocess.PIPE)
In [10]: o=pexpect.fdpexpect.fdspawn(p.stdout.fileno())
In [12]: o.expect("prompt: ")
Out[12]: 0
In [16]: p.stdin.write("foobar") #you can communicate() here, it does the same as
# these 3 steps plus protects from deadlock
In [17]: p.stdin.close()
In [18]: p.stdout.read()
Out[18]: 'foobar\n'