標籤:world 字串 roc call 通過 tin err command comm
subprocess – 建立附加進程
subprocess模組提供了一種一致的方法來建立和處理附加進程,與標準庫中的其它模組相比,提供了一個更進階的介面。用於替換如下模組:
os.system() , os.spawnv() , os和popen2模組中的popen()函數,以及 commands().
1. 運行外部命令
subprocess.call(command) 方法
subprocess的call方法可以用於執行一個外部命令,但該方法不能返回執行的結果,只能返回執行的狀態代碼: 成功(0) 或 錯誤(非0)
call()方法中的command可以是一個列表,也可以是一個字串,作為字串時需要用原生的shell來執行:
import subprocess#執行 df -hl 命令#方法1:>>> subprocess.call([‘ls‘,‘-l‘])total 8drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystemdrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp0#方法2:>>> subprocess.call("ls -l",shell=True)total 8drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystemdrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp
如上執行個體所示,雖然我們能看到執行的結果,但實際擷取的值只是狀態代碼
>>> output = subprocess.call("ls -l",shell=True)total 8drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystemdrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp>>> print(output)0
2. 錯誤處理
subprocess.check_call() 方法
我們說過call執行返回一個狀態代碼,我們可以通過check_call()函數來檢測命令的執行結果,如果不成功將返回 subprocess.CalledProcessError 異常
>>> try: subprocess.check_call("ls -t", shell=True) except subprocess.CalledProcessError as err: print("Command Error") /bin/sh: lt: command not foundCommand Error
3. 捕獲輸出結果
subprocess.check_output() 方法
call()方法啟動的進程,其標準輸入輸出會綁定到父進程的輸入和輸出。調用程式無法擷取命令的輸出結果。但可以通過check_output()方法來捕獲輸出。
# 以下測試為python3.4下運行結果>>> output=subprocess.check_output("ls -l",shell=True)>>> outputb‘total 8\ndrwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem\ndrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp\n‘>>> print(output.decode(‘utf-8‘))total 8drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystemdrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp
以下例子將chek_output()方法執行命令異常時的錯誤捕獲,而避免輸出到控制台.
try: output = subprocess.check_output("lT -l", shell=True, stderr=subprocess.STDOUT)except subprocess.CalledProcessError as err: print("Command Error", err)# 執行結果Command Error Command ‘lT -l‘ returned non-zero exit status 127
直接處理管道
subprocess.Popen()方法
函數call(), check_call() 和 check_output() 都是Popen類的封裝器。直接使用Popen會對如何運行命令以及如何處理其輸入輸出有更多控制。如通過為stdin, stdout和stderr傳遞不同的參數。
- 與進程的單向通訊
通過Popen()方法調用命令後執行的結果,可以設定stdout值為PIPE,再調用communicate()擷取結果
返回結果為tuple. 在python3中結果為byte類型,要得到str類型需要decode轉換一下
輸出結果(讀)
# 直接執行命令輸出到螢幕>>> subprocess.Popen("ls -l",shell=True)<subprocess.Popen object at 0x7febd4175198>>>> total 12drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem-rw-rw-r-- 1 ws ws 8 Feb 25 10:38 testdrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp# 不輸出到螢幕,輸出到變數>>> proc = subprocess.Popen([‘echo‘,‘"Stdout"‘],stdout=subprocess.PIPE)# communicate返回標準輸出或標準出錯資訊>>> stdout_value = proc.communicate()>>> stdout_value(b‘"Stdout"\n‘, None)>>> proc = subprocess.Popen([‘ls‘,‘-l‘],stdout=subprocess.PIPE)>>> stdout_value = proc.communicate()>>> stdout_value(b‘total 8\ndrwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem\ndrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp\n‘, None)>>>>>> print((stdout_value[0]).decode(‘utf-8‘))total 8drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystemdrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp#將結果輸出到檔案>>> file_handle = open("/home/ws/t.log",‘w+‘)>>> subprocess.Popen("ls -l",shell=True,stdout=file_handle)t.log:drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem-rw-rw-r-- 1 ws ws 8 Feb 25 10:38 test-rw-rw-r-- 1 ws ws 0 Feb 25 11:24 t.logdrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp
2 與進程的雙向通訊
>>> proc = subprocess.Popen(‘cat‘, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)>>> msg = ‘Hello world‘.encode(‘utf-8‘)# 寫入到輸入管道>>> proc.stdin.write(msg)11>>> stdout_value = proc.communicate()>>> stdout_value(b‘Hello world‘, None)# 在需要進行相互互動的輸入輸出過程也可以使用shtin來實現# 以下實現開啟python3的終端,執行一個print命令>>>proc = subprocess.Popen([‘python3‘],stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,)>>>proc.stdin.write(‘print("helloworld")‘.encode(‘utf-8‘))>>>out_value,err_value=proc.communicate()>>>print(out_value)>>> print(out_value)b‘helloworld\n‘>>> print(err_value)b‘‘
Popen.communicate()方法用於和子進程互動:發送資料到stdin,並從stdout和stderr讀資料,直到收到EOF。等待子進程結束。
捕獲錯誤輸出
>>> proc = subprocess.Popen([‘python3‘],stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,)>>> proc.stdin.write(‘print "helloworld"‘.encode(‘utf-8‘))18>>> out_value,err_value=proc.communicate()>>> out_valueb‘‘>>> print(err_value.decode(‘utf-8‘)) File "<stdin>", line 1 print "helloworld" ^SyntaxError: Missing parentheses in call to ‘print‘
Popen其它方法
- Popen.pid 查看子進程ID
Popen.returncode 擷取子進程狀態代碼,0表示子進程結束,None未結束
在使用Popen調用系統命令式,建議使用communicate與stdin進行互動並擷取輸出(stdout),這樣能保證子進程正常退出而避免出現殭屍進程。看下面例子
>>> proc = subprocess.Popen(‘ls -l‘, shell=True, stdout=subprocess.PIPE)# 當前子進程ID>>> proc.pid28906# 返回狀態為None,進程未結束>>> print(proc.returncode)None# 通過communicate提交後>>> out_value = proc.communicate()>>> proc.pid28906# 返回狀態為0,子進程自動結束>>> print(proc.returncode)0
Python模組 - subprocess