一般来说,你应该use pexpect用于交互式程序(基于对话的交互) https://stackoverflow.com/tags/subprocess/info.
您的具体问题可能是由 python 版本不匹配引起的(您认为您的代码是使用 Python 3 执行的,而实际上它可能是使用 Python 2 执行的)。第二期(EOFError
) 是预期的:要么在子脚本中捕获它,要么为子脚本提供退出信号(我在下面的代码示例中使用空行)。
下面是一个在 Python 2 上严重失败的 Python 3 代码:
#!/usr/bin/env python3
import sys
from subprocess import Popen, PIPE
with Popen([sys.executable, '-u', 'test.py'], stdin=PIPE, stdout=PIPE,
universal_newlines=True, bufsize=1) as cat:
for input_string in ["hello, world!", "and another line", ""]:
print(input_string, file=cat.stdin, flush=True)
print(cat.stdout.readline(), end='')
Note:
-
sys.exectable
是当前的 python 可执行文件(在本例中为 Python 3)
-
universal_newlines=True
启用文本模式(否则,cat.stdin
and cat.stdout
使用字节,而不是字符串)
-
-u
使孩子的输出行缓冲(否则,在子进程刷新其内部标准输出缓冲区之前,您将看不到任何内容 https://stackoverflow.com/q/20503671/4279)
- the
with
-语句关闭管道并等待子进程退出。
这是对应的test.py
:
#!/usr/bin/env python3
import time
while True:
x = input("enter something...")
if not x: # exit if the input is empty
break
print(x)
time.sleep(1)
Output
enter something...hello, world!
enter something...and another line
enter something...
注意:后面没有新行"enter something..."
它可以工作,但很脆弱,请阅读问:为什么不直接使用管道(popen())? http://pexpect.readthedocs.org/en/latest/FAQ.html#whynotpipe and use pexpect instead https://stackoverflow.com/a/23795689/4279.
如果输入是有限的并且不依赖于输出,那么您可以一次将其全部传递:
#!/usr/bin/env python3
import sys
from subprocess import check_output
output = check_output([sys.executable, 'test.py'],
input="\n".join(["hello, world!", "and another line"]),
universal_newlines=True)
print(output, end='')
此版本要求子进程正确处理 EOF:
#!/usr/bin/env python3
import time
while True:
try:
x = input("enter something...")
except EOFError:
break # no more input
print(x)
time.sleep(1)
输出是相同的(如上所示)。