1. 程式人生 > >Python subprocess.Popen子程序管道阻塞

Python subprocess.Popen子程序管道阻塞

問題產生描述

使用子程序處理一個大的日誌檔案,並對檔案進行分析查詢,需要等待子程序執行的輸出結果,進行下一步處理。

出問題的程式碼

# 啟用子程序執行外部shell命令
def __subprocess(self,cmd):
   try:
       # 執行外部shell命令, 輸出結果輸出管道
       p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)  
       p.wait()

       # 從標準輸出讀出shell命令的輸出結果
       #rt = p.stdout.read().decode()
# 以換行符拆分資料,並去掉換行符號存入列表 rt_list = rt.strip().split('\n') except Exception as e: if(DEBUG): print(traceback.format_exc()) return rt_list

問題分析

子程序產生一些資料,他們會被buffer起來,當buffer滿了,會寫到子程序的標準輸出和標準錯誤輸出,這些東西通過管道傳送給父程序。當管道滿了之後,子程序就停止寫入,於是就卡住了,及時取走管道的輸出就不會出現阻塞了

但是本人此處採取的是臨時檔案接收子程序輸出,由於臨時檔案是建立在磁碟上的,沒有size的限制,並且檔案被close後,相應的磁碟上的空間也會被釋放掉。

已改進的程式碼

import tempfile
# 啟用子程序執行外部shell命令
def __subprocess(self,cmd):
    try:
        # 得到一個臨時檔案物件, 呼叫close後,此檔案從磁碟刪除
        out_temp = tempfile.TemporaryFile(mode='w+')
        # 獲取臨時檔案的檔案號
        fileno = out_temp.fileno()

        # 執行外部shell命令, 輸出結果存入臨時檔案中
        p = subprocess.Popen(cmd, shell=True
, stdout=fileno, stderr=fileno) p.wait() # 從臨時檔案讀出shell命令的輸出結果 out_temp.seek(0) rt = out_temp.read() # 以換行符拆分資料,並去掉換行符號存入列表 rt_list = rt.strip().split('\n') except Exception as e: if(DEBUG): print(traceback.format_exc()) finally: if out_temp: out_temp.close() return rt_list