首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >了解Popen.communicate

了解Popen.communicate
EN

Stack Overflow用户
提问于 2013-05-27 15:26:55
回答 3查看 204.5K关注 0票数 73

我有一个名为1st.py的脚本,它创建了一个REPL (读取-求值-打印-循环):

代码语言:javascript
复制
print "Something to print"
while True:
    r = raw_input()
    if r == 'n':
        print "exiting"
        break
    else:
        print "continuing"

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

代码语言:javascript
复制
p = subprocess.Popen(["python","1st.py"], stdin=PIPE, stdout=PIPE)

然后尝试这样做:

代码语言:javascript
复制
print p.communicate()[0]

它失败了,提供了这样的回溯:

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

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-27 17:40:37

.communicate()写入输入(在本例中没有输入,因此它只是关闭子进程的stdin,以指示子进程没有更多的输入),读取所有输出,并等待子进程退出。

异常EOFError是由raw_input()在子进程中引发的(它需要数据,但得到了EOF (无数据))。

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

为了避免死锁,您需要异步读/写(例如,通过使用线程或select),或者确切地知道读/写的时间和数量,for example

代码语言:javascript
复制
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 来解决它)。

bufsize=1 makes the pipes line-buffered

票数 67
EN

Stack Overflow用户

发布于 2013-05-27 17:17:38

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

如下所示:

代码语言:javascript
复制
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()

要删除该错误,应执行以下操作:

代码语言:javascript
复制
all_the_process_will_tell_you = p.communicate('all you will ever say to this process\nn\n')[0]

但由于communicate关闭了stdoutstdinstderr,因此在调用communicate之后将无法读取或写入。

票数 25
EN

Stack Overflow用户

发布于 2013-05-27 15:31:22

第二段代码将第一段代码作为具有管道输入和输出的子流程开始。然后,它关闭输入并尝试读取其输出。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16768290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档