subprocess 是 python 一個很好用的模組,提供執行子程序的各種方式,最常用的就是執行,然後取得輸出結果。
import subprocess
try:
cmd_output = subprocess.check_output("ls")
except subprocess.CalledProcessError as ex:
cmd_output = ex.stdout
print("Command output:")
print(cmd_output)
接下來,因為有些指令是之前已經串好,已經加上 pipe 的了,所以會這樣用
cmd_output = subprocess.check_output("ls /usr/bin | grep python")
但你會發現 subprocess.check_output 拋出一個例外
FileNotFoundError: [Errno 2] No such file or directory: 'ls /usr/bin | grep python': 'ls /usr/bin | grep python'
這到底怎麼回事?明明就有 ls 這個執行檔?
原因很簡單,因為 subprocess.check_output 是把第一個參數視為一個檔案,所以有 pipe 的情況,他是不認可的。這時候可以加上 shell=True,讓 subprocess.check_output 知道執行第一個參數時,要先啟動 shell 來執行第一個參數裡的命令。
cmd_output = subprocess.check_output("ls /usr/bin | grep python", shell=True)
在取得輸出結果以後,cmd_output 是一個 byte 型態的變數,換言之,他不是字串。這時需要 decode 幫忙,轉換為字串:
cmd_output = cmd_output.decode('utf-8')
最後要分享的是將錯誤輸出到 null 裝置的方法,一般 bash script 裏面會用這樣的方式來將錯誤導向到 null 裝置,以避免出現不必要的輸出:
ls /usr/bin/foo 2>/dev/null
在呼叫 subprocess.check_output 時,可以帶入一個參數 stderr,而無需把 >/dev/null 寫在第一個參數裡。
cmd_output = subprocess.check_output("ls /usr/bin/foo", stderr=subprocess.DEVNULL, shell=True)
以上是自己在把 shell script 轉換為 python 時遇到的幾種狀況,因為已經遇到幾次,總是會多花一點時間回想,這次在這邊紀錄下來,以免之後又忘掉。
沒有留言:
張貼留言