了解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了stdout
和stdin
和stderr
,所以在您调用通信之后,您将无法读取或写入数据。
您的第二个代码位将第一位代码作为带pipe道input和输出的subprocess启动。 然后closuresinput并尝试读取其输出。
第一个代码试图从标准input中读取,但是启动它的过程closures了它的标准input,所以它立即到达文件结束,Python变成一个exception。