簡體   English   中英

了解Popen.communicate

[英]Understanding Popen.communicate

我有一個名為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() ,它會永遠掛起。

.communicate()寫入輸入(在這種情況下沒有輸入,因此它只關閉子進程'stdin以指示子進程沒有更多輸入),讀取所有輸出,並等待子進程退出。

子進程中的異常EOFError是由raw_input()引發的(它預期數據但得到EOF(無數據))。

p.stdout.read()永遠掛起,因為它試圖在子p.stdout.read()等待導致死鎖的輸入( raw_input() )的同時讀取子p.stdout.read() 所有輸出。

為了避免死鎖,您需要異步讀/寫(例如,通過使用線程或選擇)或確切地知道讀/寫的時間和數量,例如

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”標志來解決,該標志關閉stdin的緩沖, 節點中的 stdout )。

bufsize=1使管道在父端進行行緩沖

不要使用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]

但是由於通信會關閉stdoutstdin以及stderr ,所以在調用通信之后就無法讀取或寫入。

您的第二位代碼將第一位代碼作為帶有管道輸入和輸出的子進程啟動。 然后它關閉其輸入並嘗試讀取其輸出。

第一部分代碼嘗試從標准輸入讀取,但是啟動它的進程關閉了它的標准輸入,因此它立即到達文件結尾,Python變成了異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM