2015-02-12 65 views
0

關於如何處理子進程,異步IO輸出和避免PIPE死鎖的堆棧溢出,有很多很好的答案。雖然有些東西對我來說並沒有消失,我需要一些關於如何完成以下內容的指導。從子進程持續處理大量的stdout和stderr

我想從我的python程序運行一個子進程。子進程會產生大量的標準輸出,如果情況變差,會產生一點標準錯誤。子進程本身需要大約20分鐘才能完成。對於生成的輸出和錯誤,我希望能夠將它們記錄到終端,並將其寫入日誌文件。

做後者很容易。我剛打開兩個文件,然後設置爲Popen對象上的stdout和stderr。但是,也將輸出捕獲爲行,以便我可以將它們連續打印到終端,這讓我很煩惱。我想我可以使用poll()方法來持續輪詢。儘管如此,我仍然需要使用PIPE作爲stdout和stderr,並且在它們上調用read()會阻塞到EOF。

我想我試圖做到的是:

start the subprocess 
    while process is still running 
     if there are any lines from stdout 
      print them and write them to the out log file 
     if there are any lines from stderr 
      print them and write them to the err log file 
     sleep for a little bit 

這是否看起來是合理的?如果是這樣,有人可以解釋一下如何在不阻塞的情況下實施'if'部分。

感謝

+0

關於這個問題的其他問題表明,沒有非阻止讀取可用?這意味着你將不得不使用異步或選擇 - 否則讀取將阻塞,直到EOF。確保你正在刷新子進程中的sys.stdout。 print(flush = True)似乎不適用於我。 – user3467349 2015-02-12 01:01:00

+1

async.io:[Subprocess.Popen:將stdout和stderr都複製到終端和變量](http://stackoverflow.com/a/25960956/4279) – jfs 2015-02-12 02:02:34

+0

多線程:[Python子進程將兒童輸出到文件和終端?] (http://stackoverflow.com/a/4985080/4279) – jfs 2015-02-12 02:03:23

回答

2

這裏是我的select.select版本:

子過程(foo.py):

import time 
import sys 

def foo(): 
    for i in range(5): 
     print("foo %s" %i, file=sys.stdout,)#flush=True 
     sys.stdout.flush() 
     time.sleep(7) 
foo() 

主營:

import subprocess as sp 
import select 
proc= sp.Popen(["python", "foo.py"], stderr=sp.PIPE, stdout=sp.PIPE) 
last_line = "content" 
while last_line: 
    buff = select.select([proc.stdout], [], [], 60)[0][0] 
    if not buff: 
     print('timed out') 
     break 
    last_line = buff.readline() 
    print(last_line) 
+1

誰投下了這個票,你能解釋一下爲什麼嗎? – 2015-02-12 02:48:43

+0

我很困惑。 – user3467349 2015-02-12 03:12:48

+1

當OP詢問時,代碼也應該從'proc.stderr'中讀取。 'readline()'可能會在'select()'後面阻塞,而是使用'os.read()'。 「超時」並不意味着所有的輸出都被讀取;不要過早地打破循環。寫入輸出到一個文件也OP作出要求。使用管道的select()不適用於Windows。按照上面評論中的鏈接查看便攜式解決方案。 – jfs 2015-02-12 13:46:01