- Python自動化運維快速入門
- 鄭征
- 1016字
- 2019-12-09 14:48:19
2.4 執行外部命令subprocess
subprocess模塊是Python自帶的模塊,無須再另行安裝,它主要用來取代一些舊的模塊或方法,如os.system、os.spawn*、os.popen*、commands.*等,因此如果需要使用Python調用外部命令或任務時,則優先使用subprocess模塊。使用subprocess模塊可以方便地執行操作系統支持的命令,可與其他應用程序結合使用。因此,Python也常被稱為膠水語言。
2.4.1 subprocess.run()方法
subprocess.run()是官方推薦使用的方法,幾乎所有的工作都可以由它來完成。首先來看一下函數原型:
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)
該函數返回一個CompletedProcess類(有屬性傳入參數及返回值)的實例,雖然該函數的參數有很多,但是我們只需要知道幾個常用的就可以了。
args代表需要在操作系統中執行的命令,可以是字符串形式(要求shell=True),也可以是列表list類型。
*代表可變參數,一般是列或字典形式。
stdin、stdout、stderr指定了可執行程序的標準輸入、標準輸出、標準錯誤文件句柄。
shell代表著程序是否需要在shell上執行,當想使用shell的特性時,設置shell=True,這樣就可以使用shell指令的管道、文件名稱通配符、環境變量等,不過Python也提供了許多類shell的模塊,如glob、fnmatch、os.walk()、os.path.expandvars()、os.path.expanduser()和shutil。
check如果check設置為True,就檢查命令的返回值,當返回值為非0時,將拋出CalledProcessError異常。
timeout設置超時時間,如果超時,則強制kill掉子進程。
【示例2-20】下面舉例說明。
在Linux系統中如果我們執行一個腳本并獲取它的返回值,可有如下兩種方法,如圖2.12和圖2.13所示。
方法一:

圖2.12 獲取subprocess.run返回值(方法一)
方法二:

圖2.13 獲取subprocess.run返回值(方法二)
如果要捕獲腳本的輸出,可以按如圖2.14所示的做法。

圖2.14 捕獲腳本輸出
如果傳入參數check=True,當returncode不為0時,將會拋出subprocess.CalledProcessError異常;如果傳輸timeout參數,當運行時間超過timeout時就會拋出TimeoutExpired異常。運行結果如圖2.15所示。

圖2.15 運行結果
上面的例子雖然很長,但是為了說明超時會拋出TimeoutExpired異常,這在實際工作中非常有用,比如一個任務不確定什么時間完成,可以設置一個超時時間,如果超時仍未完成,可以通過代碼控制超時重新運行。如果超時重試3次不成功,就讓程序報錯退出。
2.4.2 Popen類
先來看一下Popen類的構造函數。

參數的說明可參見表2-5。
表2-5 Popen類構造函數的參數

使用方法如下:
subprocess.Popen(["gedit","abc.txt"]) subprocess.Popen("gedit abc.txt")
這兩個方法,后者將不會工作。因為如果是一個字符串的話,就必須是程序的路徑才可以。(考慮unix的api函數exec,接受的是字符串列表)。但是下面的可以工作:
subprocess.Popen("gedit abc.txt", shell=True)
這是因為它相當于:
subprocess.Popen(["/bin/sh", "-c", "gedit abc.txt"])
Popen類的對象還有其他實用方法,參見表2-6。
表2-6 Popen類對象的方法

2.4.3 其他方法
(1)subprocess.call(*popenargs, **kwargs):call方法調用Popen()執行程序,并等待它完成。
(2)subprocess. check_call(*popenargs, **kwargs):調用前面的call(),如果返回值非零,則拋出異常。
(3)subprocess. check_output (*popenargs, **kwargs):調用Popen()執行程序,并返回其標準輸出。