使用Python中的管道与进程通信

时间:2015-02-02 12:54:13

标签: python pipe subprocess

我有一个进程可以在命令行上进行通信,如下所示:

% process -
input
^D^D
output

所以:我开始这个过程,键入一些输入,然后按两次Ctrl-D后,我得到了输出。 我想围绕这个过程制作一个Python包装器。我创造了这个:

from subprocess import Popen, PIPE

p = Popen('process -', stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
while True:
        input = raw_input('Enter input: ')
        p.stdin.write(input)
        p.stdin.close()
        p.wait()
        output = p.stdout.read()
        print output

这是第一次有效,但之后我得到了:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    p.stdin.write(input)
ValueError: I/O operation on closed file

是否有其他方式可以在不关闭文件的情况下与此流程进行交互?

3 个答案:

答案 0 :(得分:0)

p.wait()将等到子流程退出之前退出,因此在脚本的第二次迭代中,p已经退出(因此已关闭p.stdin)。

答案 1 :(得分:0)

如果你的包裹过程在第一次输出后结束,则通讯将失败到第二次。由于所有管道(stdin和stdout)将被关闭。因此错误:

ValueError: I/O operation on closed file

每次尝试向包装过程发送输入时,都必须预期必须打开输入和管道。

另一方面,托马斯在答案中说,p.wait()不是重复输入/输出策略的方法。

由于内部调用subprocess.Popen.communicate(),因此您无法使用subprocess.Popen.wait()

您可以尝试使用p.stdin.writep.stdout.read这里有一篇关于这个主题的好文章:Writing to a python subprocess pipe

答案 2 :(得分:0)

模拟shell会话:

$ process -
input
^D^D
output

在Python中,使用check_output()

#!/usr/bin/env python3
from subprocess import check_output

out = check_output(['process', '-'], input='input\n', universal_newlines=True)
print(out, end='')

Ctrl + D 被Unix终端($ stty -a - 识别为EOF(终止输入) - 在输出中查找eof = ^Dicanon )。如果您需要输入 Ctrl + D 两次(at the beginning of a line);它可能表示process计划中存在错误,例如"for line in sys.stdin: doesn't notice EOF the first time" Python bug