理解波本,交流

我有一个名为 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()时,它会永远挂起。

237788 次浏览

第二段代码将第一段代码作为子进程启动,并通过管道输入和输出。然后关闭它的输入并尝试读取它的输出。

第一段代码尝试从标准输入读取,但是启动它的进程关闭了它的标准输入,因此它立即到达文件末尾,Python 将其转换为异常。

不要使用通信(input = “”)。它将输入写入进程,关闭其标准输入,然后读取所有输出。

这样做:

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]

但是由于通信关闭了 stdoutstdin以及 stderr,所以在呼叫通信之后就不能读写了。

.communicate()写入输入(在这种情况下没有输入,所以它只是关闭子进程的 stdin 以向子进程表明没有更多的输入) ,读取所有输出,然后等待子进程退出。

异常 EOFError 在子进程中由 raw_input()引发(它期望得到数据,但得到了 EOF (没有数据))。

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

为了避免死锁,你需要异步读/写(例如,通过使用线程或选择)或准确地知道什么时候和多少读/写,比如说:

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

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

注意 块缓冲问题块缓冲问题(这里是通过使用 在子元素 中关闭 stdin、 stdout < em > 缓冲的“-u”标志来解决的)。

bufsize=1使管道线路缓冲 在父母那边