快轉到主要內容
  1. posts/

[Python] os.system() VS subprocess.run()

·
Python
目錄

簡介
#

如果想要在 Python 中執行 shell 指令,有兩種常見的方法可以使用,其中一種是 os.system(),另一種則是 subprocess.run()

os.system()
#

import os

os.system('echo hello world')

os.system 會把傳入的參數作為 shell 指令,並將執行結果輸出到 stdout,最後回傳該指令執行後的回傳值 (0 代表成功,非 0 代表發生錯誤)。

因為 os.system 安全性較差,可能會產生 shell injection 的問題,已經開始逐漸被 subprocess 給取代。

subprocess.run()
#

相較 os.systemsubprocess.run 除了擁有較高的安全性,它還有很高的靈活性,可以擷取指令的輸出,讓 Python 可以再對其進行額外的處裡。

subprocess.run 在呼叫上與 os.system 有點不一樣,os.system 可以直接將指令與參數透過 string 傳入,但 subprocess.run 在呼叫時,必須要把指令與參數以空格做區分,轉換成 list 來傳入。例如 ls -l,需要改成 ['ls', '-l']

在執行完 shell 指令後,subprocess.run 會回傳一個 CompletedProcess 物件,其中包含了執行的指令、輸出以及回傳值。

import subprocess

res = subprocess.run(["echo", "hello world!"], capture_output=True)

print(res.returncode)  # 0
print(res.stdout.decode())  # hello world!

subprocess.CompletedProcess 物件
#

args
#

執行 process 的參數,可以是 string 或是 list。

returncode
#

child process 執行結束的回傳值 (一般來說 0 代表成功,非 0 代表發生錯誤)。

stdout
#

child process 的 stdout。

必須在 subprocess.run() 傳入 capture_output=True,否則 stdout 的值會是 None

資料型態是一個 bytes sequence,如果 subprocess.run() 傳入了參數 encodingerrors 或是 text = True,則資料型態會是 string。

stderr
#

child process 的 stderr。

必須在 subprocess.run() 傳入 capture_output=True,否則 stderr 的值會是 None

資料型態是一個 bytes sequence,如果 subprocess.run() 傳入了參數 encodingerrors 或是 text = True,則資料型態會是 string。

check_returncode()
#

如果 returncode 為非 0,則會拋出例外 CalledProcessError

Rerferance
#

subprocess

Calling Shell Commands from Python: OS.system vs Subprocess