了解Popen.communicate

我有一个名为1st.py的脚本,它创build了一个REPL(read-eval-print-loop):

 print "Something to print" while True: r = raw_input() if r == 'n': print "exiting" break else: print "continuing" 

然后我用以下代码启动1st.py

 p = subprocess.Popen(["python","1st.py"], stdin=PIPE, stdout=PIPE) 

然后尝试这个:

 print p.communicate()[0] 

它失败了,提供这个追溯:

 Traceback (most recent call last): File "1st.py", line 3, in <module> r = raw_input() EOFError: EOF when reading a line 

你能解释一下这里发生了什么事吗? 当我使用p.stdout.read() ,它永远挂起。

.communicate()写入input(在这种情况下没有input,所以它只是closuressubprocessstdin以向subprocess指示没有更多input),读取所有输出,并等待subprocess退出。

在subprocess中由raw_input()引发exceptionEOFError(它是预期的数据,但得到了EOF(无数据))。

p.stdout.read()永远挂起,因为它试图在子级等待导致死锁的input( raw_input() )的同时读取子级的所有输出。

为了避免死锁,您需要asynchronous读/写(例如,通过使用线程或select)或准确知道何时读取和写入多less, 例如 :

 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 

注意:如果读/写不同步,这是一个非常脆弱的代码; 它僵局。

注意块缓冲问题 (在这里它通过使用“-u”标志来closures缓冲标准input,标准输出在孩子 )解决。

bufsize=1使pipe道在父端进行行缓冲 。

不要使用沟通(input=“”)。 它将input写入进程,closuresstdin,然后读取所有输出。

像这样做:

 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() 

你会做什么来消除错误:

 all_the_process_will_tell_you = p.communicate('all you will ever say to this process\nn\n')[0] 

但是由于通信closures了stdoutstdinstderr ,所以在您调用通信之后,您将无法读取或写入数据。

您的第二个代码位将第一位代码作为带pipe道input和输出的subprocess启动。 然后closuresinput并尝试读取其输出。

第一个代码试图从标准input中读取,但是启动它的过程closures了它的标准input,所以它立即到达文件结束,Python变成一个exception。