2013-05-02 301 views
9

我發現很多類似的問題在Python中運行時詢問對象的大小。一些答案建議設置子進程的內存量限制。我不想限制子進程的內存。這是我想要的 -Python - 數據subprocess.Popen的限制數量可以產生

我使用subprocess.Popen()執行外部程序。完成後,我可以很好地獲得標準輸出並輸入process.stdout.readlines()process.stderr.readlines()

我有一個問題,當一個錯誤的程序進入無限循環並不斷產生輸出。由於subprocess.Popen()將輸出數據存儲在內存中,所以無限循環會迅速消耗整個內存並且程序變慢。

一個解決方案是我可以在超時運行命令。但是程序需要不同的時間才能完成。對於節目花費時間很短並且具有無限循環的節目來說,超時時間太長,使得它失去了目的。

有什麼簡單的方法,我可以把一個上限說200MB上的命令可以產生的數據量?如果超過限制命令應該被殺死。

+0

一旦管道緩衝區已滿,子進程不會減慢速度。它會完全停止,直到您讀取數據。如果您需要同時讀取多個管道,那麼您可以使用線程或'select'或'fcntl'模塊來讀取管道而不會阻塞。 – jfs 2014-02-24 04:02:31

回答

4

第一:它不是subprocess.Popen()存儲數據,但它是「我們」和「我們」子流程之間的管道。

在這種情況下,您不應該使用readlines(),因爲這將無限期地緩衝數據,並且只在最後將它們作爲列表返回(在這種情況下,實際上是存儲數據的這個函數)。

如果你這樣做

bytes = lines = 0 
for line in process.stdout: 
    bytes += len(line) 
    lines += 1 
    if bytes > 200000000 or lines > 10000: 
     # handle the described situation 
     break 

,你可以在你的問題作爲通緝。但是你不應該忘記在之後殺死子進程,以阻止它產生更多的數據。

但是,如果你想照顧stderr以及,你必須嘗試複製process.communicate()的行爲與select()等,並採取適當的行動。

+3

快速提示:如果您在'if ... ...或lines ...:'內執行'break',則根據此示例,您將停止從管道中「消費」數據,並且您的子進程將阻止嘗試寫入完整的標準輸出管道。 此時,您應該繼續使用(並放棄)數據或終止子進程。 – fmoo 2013-05-02 07:39:05

+0

@fmoo完全正確。因爲子進程可能會處於無限循環狀態,所以消除和丟棄數據可能會變得冗長,但殺死它似乎是合適的。 – glglgl 2013-05-02 07:48:54

+0

如果OP還需要讀取'stderr',它可能會失敗。如果子進程填充了stderr管道緩衝區,那麼父塊永遠試圖從'進程讀取。stdout'而子進程試圖寫入其stderr。 – jfs 2014-02-24 04:06:00

相關問題