2017-07-03 48 views
1

是否有一種簡單的方式來收集子進程的輸出而不實際等待呢?在Python中收集子進程輸出非阻塞

我可以考慮創建一個subprocess.Popen()捕獲它的標準輸出,然後調用p.communicate(),但這會阻塞,直到子進程終止。

我能想到使用subprocess.check_output()或類似的,但也會阻止。

我需要一些東西,我可以開始,然後做其他的東西,然後檢查子進程是否被終止,如果是,則取其輸出。

我能想到的兩個較爲複雜的方式來實現這一目標:

  1. 將輸出重定向到一個文件,然後終止後我可以讀取該文件的輸出。
  2. 實現並啓動一個處理線程(!),它不斷嘗試從子進程的stdout讀取數據並將其添加到緩衝區。

第一個需要臨時文件和磁盤I/O,我不喜歡在我的情況。第二個意思是實現相當多。

我想可能有一種我現在還沒有想到的更簡單的方法,或者在某些我還沒有找到的庫中使用現成的解決方案。

+0

「進程中的一個線程」的方法並不複雜。你需要一個例子嗎? –

回答

1

在線程中調用check_output有什麼不對?

import threading,subprocess 

output = "" 

def f(): 
    global output 
    output = subprocess.check_output("ls") # ["cmd","/c","dir"] for windows 


t = threading.Thread(target=f) 
t.start() 
print('Started') 
t.join() 
print(output) 

注意,一個可能會傾向於使用p = subprocess.Popen(cmd,stdout=subprocess.PIPE),等待p.poll()是= None和嘗試讀取p.stdout算賬:只有當輸出是小作品,否則你會得到一個僵局,因爲stdout緩衝區完整的,你必須不時閱讀它。

使用p.stdout.readline()會起作用,但如果該過程沒有定期打印,也會阻止。如果您的應用程序始終打印輸出,則可以將其視爲非阻塞,並且解決方案可以接受。

+0

我需要並行啓動一堆進程。我不知道他們將以何種順序完成,但我知道他們都在生產產量。每當完成時,我想收集它的輸出並立即使用它。隨着你的線程方法,我需要等待(任何出)一堆線程。我想我會使用Queue來做到這一點。但是這聽起來相當複雜。並且爲了讓子進程和每個進程在主進程中有一個額外的線程,聽起來就像將結構加倍一樣。我認爲,我寧願去臨時文件的方式。 – Alfe

+0

相關:https://stackoverflow.com/questions/375427/non-blocking-read-on-a-subprocess-pipe-in​​-python?rq = 1 –

0

我想你想要的是一個無緩衝的標準輸出流。因此,您將能夠捕獲流程的輸出而無需等待它完成。 您可以通過subprocess.Popen()函數和參數stdout=subprocess.PIPE來實現。

嘗試這樣的事情

proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 

line = proc.stdout.readline() 
while line: 
    print line 
    line = proc.stdout.readline() 
+0

我需要有幾個並行的,我不知道哪個將是多快,哪些將完成時。但是我想在子進程結束後立即使用子進程的輸出。 – Alfe