在 Python 中調用外部進程是很常見的需求,如下爲幾種常見的方法。java
這個方法實際上調用的是系統的 C 函數 system(), 命令以字符串的形式傳入,在系統子 shell 中執行,和在真實的 shell 執行一致。python
優勢:能夠利用 shell 的管道和重定向等特性來實現比較複雜的命令。git
import os
# 使用管道獲取全部java進程並強制殺掉
os.system('ps -ef|grep java|cut -c 9-15|xargs kill -9')
# 獲取當前目錄下全部png圖片文件名並重定向到png_list.txt中
os.system('ls *.png > png_list.txt')
複製代碼
缺點:外部進程的輸出沒法被 python 代碼捕獲,system 函數只返回一個 exit status,此外做爲命令傳入的字符串必須是有效的命令,不然會出現意想不到的結果。web
與上一種不一樣的是,os.popen 會開闢一個管道並將輸出經過一個 file-like 的對象返回給調用者,相似 python 中文件操做方法 open 同樣。shell
import os
with os.popen('ls *.png', mode='r') as res:
result = res.read()
複製代碼
這個是 python 自帶庫 subprocess 中的 Popen 類,做爲 os.popen 的替代,擁有更多可選參數。服務器
import subprocess
# 當 shell=True 時,POSIX 類系統默認會調用 /bin/sh 來執行傳入的命令
result = subprocess.Popen(['ls', '-l'], shell=True, stdout=subprocess.PIPE).stdout.read()
複製代碼
這個函數擁有相似 Popen 類的可選參數,可是會等待子進程運行完畢再返回一個返回碼。markdown
import subprocess
return_code = subprocess.call(['ls', '-l'], shell=True)
複製代碼
這個函數在 python3.5 及之後的版本可用,有幾個很是有用的參數可選,該函數返回的是一個 CompletedProcess 對象,經過該對象能夠獲取標準輸入和輸出。svg
import subprocess
# 在shell中執行並獲取標準輸出和錯誤
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 能夠配合 shlex 庫分割指令字符串
# subprocess.run(shlex.split('ls -l))
print(result.stdout)
print(result.stderr)
# 對返回值進行檢查, 若是子程序返回錯誤那麼拋出一個CalledProcessError的異常
result = subprocess.run(['ls', '-l'],check=True)
# 給子程序加上超時限制, 若是超時, 向上拋出TimeoutExpired異常, 在項目中控制外部進程用時是比較好的習慣
result = subprocess.run(['sleep', '5'], timeout=3)
複製代碼
from fabric import operations
res = operations.local('ls -l', capture=True)
# 在遠程服務器上執行命令,但須要提早配置好登錄信息
res = operations.run('cmd')
複製代碼
其經過動態解析 $PATH 來執行二進制命令,執行並非 Python 類或函數,而是用 python 包裝了系統 PATH 中的可執行命令,也就是說系統路徑中全部命令都是能夠執行的。函數
# 安裝
pip install sh
# 執行各類系統命令
sh.ls('-l', '/data')
sh.ifconfig()
# 使用管道,並獲取返回值
count = sh.wc(sh.ls('-l'), '-l')
# 甚至可使用子命令
sh.git.status()
# 將命令放在後臺運行
p = sh.find('-name', 'sh.py', _bg=True)
# 幹其餘事
p.wait()
複製代碼
我的優先推薦官方庫中的 subprocess 模塊中的 run 函數,簡單易用。oop