python subprocess多个stdin.write和stdout.read

时间:2015-10-24 01:22:10

标签: python python-3.x pipe subprocess

感谢您抽出宝贵时间回答这个问题。我正在玩Python 3.4,我有两个简单的python程序。一个是一个名为test.py的程序,它接受用户输入并打印一些内容。

while True:
    print("enter something...")
    x = input()
    print(x)
    time.sleep(1)

要向此程序发送输入,我有另一个使用子进程的程序:

from subprocess import Popen, PIPE

cat = Popen('python test.py', shell=True, stdin=PIPE, stdout=PIPE)
cat.stdin.write("hello, world!\n")
cat.stdin.flush()
print(cat.stdout.readline())

cat.stdin.write("and another line\n")
cat.stdin.flush()
print(cat.stdout.readline())

然而,当我运行上述程序时,我收到一个错误:

enter something...

hello, world!
Traceback (most recent call last):
  File "/opt/test.py", line 9, in <module>
    x = input()
EOFError: EOF when reading a line
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe

如果我将test.py替换为标准的linux命令,例如&#39; cat&#39;,事情会按预期工作。

有没有办法发送多个stdin写入并读回多个stdout?

1 个答案:

答案 0 :(得分:3)

一般情况下,您应该use pexpect for interactive programs (dialog-based interactions)

您的具体问题可能是由python版本不匹配引起的(您认为您的代码是使用Python 3执行的,而实际上它可能是使用Python 2执行的)。第二个问题(#!/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='') )是预期的:要么在子脚本中捕获它,要么为子进程提供信号(我在下面的代码示例中使用空行)。

这是在Python 2上大声失败的Python 3代码:

sys.exectable

注意:

这是相应的#!/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)

enter something...hello, world!
enter something...and another line
enter something...

输出

"enter something..."

注意:#!/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='')

之后没有换行

它有效,但很脆弱,请阅读Q: Why not just use a pipe (popen())?use pexpect instead

如果输入是有限的并且它不依赖于输出,那么你可以立即传递它:

#!/usr/bin/env python3
import time

while True:
    try:
        x = input("enter something...")
    except EOFError:
        break # no more input

    print(x)
    time.sleep(1)

此版本要求孩子正确处理EOF:

{{1}}

输出相同(如上所示)。