Python 了解 Popen.communicate
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/16768290/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Understanding Popen.communicate
提问by Black_Hat
I have a script named 1st.pywhich creates a REPL (read-eval-print-loop):
我有一个名为1st.py创建 REPL(读取-评估-打印-循环)的脚本:
print "Something to print"
while True:
    r = raw_input()
    if r == 'n':
        print "exiting"
        break
    else:
        print "continuing"
I then launched 1st.pywith the following code:
然后我1st.py使用以下代码启动:
p = subprocess.Popen(["python","1st.py"], stdin=PIPE, stdout=PIPE)
And then tried this:
然后尝试了这个:
print p.communicate()[0]
It failed, providing this traceback:
它失败了,提供了这个回溯:
Traceback (most recent call last):
  File "1st.py", line 3, in <module>
    r = raw_input()
EOFError: EOF when reading a line
Can you explain what is happening here please? When I use p.stdout.read(), it hangs forever.
你能解释一下这里发生了什么吗?当我使用时p.stdout.read(),它永远挂起。
采纳答案by jfs
.communicate()writes input (there is no input in this case so it just closes subprocess' stdin to indicate to the subprocess that there is no more input), reads all output, and waits for the subprocess to exit.
.communicate()写入输入(在这种情况下没有输入,因此它只是关闭子进程的 stdin 以指示子进程没有更多输入),读取所有输出,并等待子进程退出。
The exception EOFError is raised in the child process by raw_input()(it expected data but got EOF (no data)).
异常 EOFError 在子进程中由raw_input()(它期望数据但得到 EOF(无数据))引发。
p.stdout.read()hangs forever because it tries to read alloutput from the child at the same time as the child waits for input (raw_input()) that causes a deadlock.
p.stdout.read()永远挂起,因为它试图在孩子等待导致死锁的输入 ( )的同时读取孩子的所有输出raw_input()。
To avoid the deadlock you need to read/write asynchronously (e.g., by using threads or select) or to know exactly when and how much to read/write, for example:
为了避免死锁,您需要异步读/写(例如,通过使用线程或选择)或确切知道读/写的时间和数量,例如:
from subprocess import PIPE, Popen
p = Popen(["python", "-u", "1st.py"], stdin=PIPE, stdout=PIPE, bufsize=1)
print p.stdout.readline(), # read the first line
for i in range(10): # repeat several times to show that it works
    print >>p.stdin, i # write input
    p.stdin.flush() # not necessary in this case
    print p.stdout.readline(), # read output
print p.communicate("n\n")[0], # signal the child to exit,
                               # read the rest of the output, 
                               # wait for the child to exit
Note: it is a very fragile code if read/write are not in sync; it deadlocks.
注意:如果读/写不同步,这是一个非常脆弱的代码;它陷入僵局。
Beware of block-buffering issue(here it is solved by using "-u" flag that turns off buffering for stdin, stdout in the child).
当心块缓冲问题(这里通过使用“-u”标志来解决它,该标志关闭了 stdin 的缓冲, stdout在 child 中)。
回答by icktoofay
Your second bit of code starts the first bit of code as a subprocess with piped input and output. It then closes its input and tries to read its output.
您的第二位代码将第一位代码作为具有管道输入和输出的子进程开始。然后关闭其输入并尝试读取其输出。
The first bit of code tries to read from standard input, but the process that started it closed its standard input, so it immediately reaches an end-of-file, which Python turns into an exception.
代码的第一位尝试从标准输入读取,但启动它的进程关闭了它的标准输入,因此它立即到达文件结尾,Python 变成了异常。
回答by User
Do not use communicate(input=""). It writes input to the process, closes its stdin and then reads all output.
不要使用通信(输入=“”)。它将输入写入进程,关闭其标准输入,然后读取所有输出。
Do it like this:
像这样做:
p=subprocess.Popen(["python","1st.py"],stdin=PIPE,stdout=PIPE)
# get output from process "Something to print"
one_line_output = p.stdout.readline()
# write 'a line\n' to the process
p.stdin.write('a line\n')
# get output from process "not time to break"
one_line_output = p.stdout.readline() 
# write "n\n" to that process for if r=='n':
p.stdin.write('n\n') 
# read the last output from the process  "Exiting"
one_line_output = p.stdout.readline()
What you would do to remove the error:
您将如何消除错误:
all_the_process_will_tell_you = p.communicate('all you will ever say to this process\nn\n')[0]
But since communicate closes the stdoutand stdinand stderr, you can not read or write after you called communicate.
但是由于communicate 关闭了stdoutandstdin和stderr,所以在调用了communication 之后就不能读或写了。

