我有一个名为1st.py
的脚本,它创建了一个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()
时,它会永远挂起。
答案 0 :(得分:48)
.communicate()
写入输入(在这种情况下没有输入,因此它只关闭子进程'stdin以指示子进程没有更多输入),读取所有输出,并等待子进程退出。
异常EOFError在子进程中由raw_input()
引发(它预期数据但得到EOF(无数据))。
p.stdout.read()
永远挂起,因为它试图在孩子等待导致死锁的输入(raw_input()
)的同时读取孩子的所有输出。< / p>
为了避免死锁,您需要异步读/写(例如,通过使用线程或选择)或确切地知道读/写的时间和内容,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
注意:如果读/写不同步,它是一个非常脆弱的代码;它陷入僵局。
谨防block-buffering issue(此处使用"-u" flag that turns off buffering for stdin, stdout in the child解决)。
答案 1 :(得分:19)
不要使用communication(input =“”)。它将输入写入进程,关闭其stdin,然后读取所有输出。
这样做:
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]
但是,由于通信会关闭stdout
和stdin
以及stderr
,因此在您致电通信后无法读取或写入。
答案 2 :(得分:0)
您的第二位代码将第一位代码作为带有管道输入和输出的子进程启动。然后它关闭输入并尝试读取其输出。
第一部分代码尝试从标准输入读取,但启动它的进程关闭了它的标准输入,因此它立即到达文件结尾,Python变成异常。