天天看點

python os.popen阻塞_關于os.popen你可能不知道的

一前言

使用python執行一些指令或調用第三方工具是比較常見的情況,實作的方法也很多,如os.system(),os.popen()、subprocess子產品中的函數等等,本文主要介紹一下os.popen(),可能隐藏着你不曾接觸的知識點,同時會結合執行個體進行說明,便于了解。

二文法格式

首先我們看下os.popen的文法格式,如下:

os.popen(cmd, mode='r', buffering=-1)

參數說明:

Command --- 調用的指令;

mode --- 模式權限可以是 'r'(預設) 或 'w';

bufsize -- 指明了檔案需要的緩沖大小:0意味着無緩沖;1意味着行緩沖;其它正值表示使用參數大小的緩沖(大概值,以位元組為機關);負的bufsize意味着使用系統的預設值。

官方釋義:

Open a pipe to or from command cmd. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is 'r' (default) or 'w'.

從指令cmd打開一個管道,傳回值是連接配接管道的檔案對象,通過該對象可以進行讀或寫。

三知識點梳理

1.傳回值是檔案對象

注意:傳回值是檔案對象,既然是檔案對象,使用完就應該關閉,對吧?!不信網上搜一下,一大把文章提到這個os.popen都是忘記關閉檔案對象的。 是以,推薦的寫法是:

with os.popen(command, "r") as p:

r = p.read()

至于with的用法就不多講了,使用它,不需要顯式的寫p.close()。

2.非阻塞

通俗的講,非阻塞就是os.popen不會等cmd指令執行完畢就繼續下面的代碼了,不信?!看下面代碼執行個體:

python os.popen阻塞_關于os.popen你可能不知道的

從上面執行個體可知,os.popen執行打開Uedit32.exe這個工具,但從實際執行結果看,Uedit32.exe還沒打開,就直接進入了下一條語句,列印了“hello 小蟒社群”。在某些應用場景,可能這并不是你期望的行為,那如何讓指令執行完後,再執行下一句呢?

處理方法是使用read()或readlines()對指令的執行結果進行讀操作。

3.完全阻塞

上面寫了該函數是非阻塞的,現在怎麼又變成完全阻塞的呢?感覺一頭霧水了吧。本質上os.popen是非阻塞的,為了實作阻塞的效果,我們使用read()或readlines()對指令結果進行讀,由此産生了阻塞的效果。但是,如果你的指令執行無法退出或進入互動模式,這種“讀”将形成完全阻塞的情況,表現的像程式卡住了。

看下面代碼執行個體1:

python os.popen阻塞_關于os.popen你可能不知道的

os.popen執行了ping  127.0.0.1  -t 該指令會一直執行,除非CTRL+C強制退出,因而,執行readlines讀取指令輸出時會造成卡住。

代碼執行個體2:

使用os.popen執行sqlplus指令對資料庫進行操作的場景,如果sqlplus執行失敗,會進入互動模式,如圖所示,此時使用readlines()讀取執行結果時也會卡死,效果如上圖:

python os.popen阻塞_關于os.popen你可能不知道的

四總結

os.popen()在大多數場景都是挺好用友善的,但是也有坑!! 具體應用中,需要注意下。

建議:

1.在需要讀取指令執行結果時,避免在指令無法退出或進入互動模式的場景應用os.popen;

2.os.popen()無法滿足需求時,可以考慮subprocess.Popen();

五其他資源

關于python學習、分享、交流,筆者開通了微信公衆号【小蟒社群】,感興趣的朋友可以關注下,歡迎加入,建立屬于我們自己的小圈子,一起學python。