Python subprocess.Popen子程序管道阻塞
阿新 • • 發佈:2019-02-04
問題產生描述
使用子程序處理一個大的日誌檔案,並對檔案進行分析查詢,需要等待子程序執行的輸出結果,進行下一步處理。
出問題的程式碼
# 啟用子程序執行外部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