Subprocess 介紹
subprocess 模組是 Python 標準庫中的一個模組,用於管理子程序(子程式)。透過 subprocess 模組,可以在 Python 指令碼中啟動新的程序、連線到它們的輸入/輸出流以及獲取它們的返回值。
Subprocess 主要功能
1. 執行外部命令:subprocess 允許你在 Python 指令碼中執行系統命令或其他可執行檔案。
2. 程序管理:你可以啟動新的程序並與其互動,監視它們的狀態以及等待它們的完成。
3. 輸入/輸出重定向:透過 subprocess,你能夠重定向程序的標準輸入、輸出和錯誤流,實現和外部程序的互動。
subprocess.run()
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None, **other_popen_kwargs)
用途:執行命令並等待其完成。
返回值:CompletedProcess 物件,包含執行結果和輸出。
CompletedProcess 物件方法:
args:執行的命令及其引數列表。
returncode:命令的返回狀態碼(0 表示成功)。
stdout:命令的標準輸出(以位元組或字串形式,取決於引數)。
stderr:命令的標準錯誤輸出(以位元組或字串形式,取決於引數)。
check_returncode(): 命令的狀態碼,如果 returncode 非零, 丟擲 CalledProcessError.
引數:
args:一個字串列表,表示要執行的命令及其引數。例如:['ls', '-l']。
stdin, input:用於指定子程序的標準輸入。如果 stdin 引數被設定為 subprocess.PIPE,則可以向子程序寫入資料。input 引數用於向子程序提供輸入資料。
stdout, stderr:用於指定子程序的標準輸出和錯誤輸出。這些引數可以是 subprocess.PIPE(用於捕獲輸出),或者是檔案物件(用於將輸出重定向到檔案)。
capture_output:一個布林值,用於決定是否捕獲子程序的標準輸出和錯誤輸出。預設為 False。如果設定為 True,則 stdout 和 stderr 引數會被忽略,輸出會被捕獲並返回為位元組串(如果 text 引數為 True,則為字串)。
shell:一個布林值,用於指示是否透過 shell 執行命令。預設為 False。如果設定為 True,則命令會由 shell 解析,這可能會帶來安全風險(因為可能受到命令注入攻擊)。
cwd:一個字串,指定子程序的當前工作目錄。預設為當前工作目錄。
timeout:一個浮點數,指定命令執行的最長時間(秒)。如果命令執行時間超過這個時間,子程序會被終止。
check:一個布林值,用於指示是否檢查命令的退出狀態碼。如果設定為 True 且命令返回非零退出狀態碼,會丟擲一個 CalledProcessError 異常。
encoding 和 errors:這兩個引數用於處理輸出的文字編碼問題。如果 capture_output 或 text 引數為 True,則使用這些引數來解碼位元組輸出。
text:一個布林值,用於指示是否以文字模式執行子程序。與 capture_output 引數結合使用,如果兩者都為 True,則輸出將被捕獲並作為字串返回。預設為 None(根據 Python 版本和平臺自動推斷)。
env:一個字典,用於指定子程序的環境變數。預設使用父程序的環境變數。
示例
import subprocess
try:
result = subprocess.run(['ping', 'www.baidu.com' ], capture_output=True, text=True, check=True)
print(1, result.stdout)
print(2, result.returncode)
print(3, result.stderr)
print(4, result.args)
print(5, result.check_returncode())
except subprocess.CalledProcessError as e:
print(f"Error: {e.stderr}") # 輸出錯誤資訊
輸出:
1
正在 Ping www.a.shifen.com [110.242.68.4] 具有 32 位元組的資料:
來自 110.242.68.4 的回覆: 位元組=32 時間=15ms TTL=53
來自 110.242.68.4 的回覆: 位元組=32 時間=11ms TTL=53
來自 110.242.68.4 的回覆: 位元組=32 時間=12ms TTL=53
來自 110.242.68.4 的回覆: 位元組=32 時間=11ms TTL=53
110.242.68.4 的 Ping 統計資訊:
資料包: 已傳送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計時間(以毫秒為單位):
最短 = 11ms,最長 = 15ms,平均 = 12ms
2 0
3
4 ['ping', 'www.baidu.com']
5 None
subprocess.Popen()
subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, group=None, extra_groups=None, user=None, umask=-1, encoding=None, errors=None, text=None, pipesize=-1, process_group=None)
用途:啟動子程序,支援非阻塞執行和靈活的輸入輸出處理。
引數:
args: 一個包含命令和命令引數的列表(例如 ['ls', '-l'])。
bufsize: I/O緩衝策略,預設是-1表示使用系統預設緩衝。
executable: 如果指定了shell=True,這個引數用來指定shell的路徑。
stdin, stdout, stderr: 分別代表子程序的標準輸入、輸出和錯誤流。預設是None,表示繼承父程序的標準流。可以透過管道連線它們以實現資料通訊。
preexec_fn: 在子程序啟動之前執行的函式。通常用於設定環境變數或修改程序屬性。
close_fds: 如果為True,關閉檔案描述符(預設開啟)。通常是為了安全考慮。
shell: 如果為True,使用shell來執行命令(有安全風險)。
cwd: 子程序的當前工作目錄。如果不指定,則使用父程序的當前工作目錄。
env: 一個字典,用於定義子程序的環境變數。如果不指定,則使用父程序的環境變數。
universal_newlines: 如果為True,使用文字模式進行檔案讀寫(Python 3中預設是True)。
startupinfo 和 creationflags: 與Windows平臺相關,用於配置子程序的啟動資訊和建立標誌。
restore_signals: 是否恢復原始訊號處理程式(在Unix平臺上)。預設是True。
start_new_session: 如果為True並且平臺支援,新程序會建立新的會話(用於控制終端視窗等)。
pass_fds: 一個檔案描述符列表,這些描述符會被傳遞到子程序(僅適用於Unix平臺)。用於檔案描述符的複用通訊。
group, extra_groups, user, umask: 這些引數用於設定子程序的許可權和組屬性(主要在Unix平臺上)。
encoding 和 errors: 用於指定子程序的文字編碼方式和處理錯誤的策略。僅在universal_newlines=True時有效。如果未指定,則使用預設編碼方式處理錯誤。
Popen 類的例項擁有方法:
communicate(input=None, timeout=None):
與程序互動:將資料傳送到 stdin。 從 stdout 和 stderr 讀取資料,直到抵達檔案結尾。 等待程序終止並設定 returncode 屬性。 可選的 input 引數應為要傳送到下級程序的資料,或者如果沒有要傳送到下級程序的資料則為 None。 如果流是以文字模式開啟的,則 input 必須為字串。 在其他情況下,它必須為位元組串。
communicate() 返回一個 (stdout_data, stderr_data) 元組。如果檔案以文字模式開啟則為字串;否則位元組。
timeout 設定超時時間(單位為秒)。
wait(timeout=None):
等待子程序被終止。設定並返回 returncode 屬性。
poll():
檢查子程序的狀態。返回子程序的退出碼,如果子程序仍在執行則返回 None。
terminate():
傳送 SIGTERM 訊號以終止子程序。
kill():
傳送 SIGKILL 訊號以強制終止子程序。
send_signal(signal):
向子程序傳送指定的訊號。
args:
args 引數傳遞給 Popen -- 一個程式引數的序列或者一個簡單字串。
pid:
子程序的程序號。
returncode:
子程序的返回碼。 初始為 None
stdout
如果 stdout 引數為 PIPE,此屬性是一個類似 open() 所返回物件的可讀流物件。 從流中讀取將會提供來自子程序的輸出。 如果 encoding 或 errors 引數被指定或者 text 或 universal_newlines 引數為 True,則這個流將是一個文字流,否則將是一個位元組流。 如果 stdout 引數不為 PIPE,則此屬性將為 None。
stderr
如果 stderr 引數為 PIPE,此屬性是一個類似 open() 所返回物件的可讀流物件。 從流中讀取將會提供來自子程序的錯誤輸出。 如果 encoding 或 errors 引數被指定或者 text 或 universal_newlines 引數為 True,則這個流將是一個文字流,否則將是一個位元組流。 如果 stderr 引數不為 PIPE,則此屬性將為 None。
stdin
如果 stdin 引數為 PIPE,此屬性是一個類似 open() 所返回物件的可寫流物件。 如果指定了 encoding 或 errors 引數或者 text 或 universal_newlines 引數為 True,則這個流將是一個文字流,否則將是一個位元組流。 如果 stdin 引數不為 PIPE,則此屬性將為 None。
示例
import subprocess
try:
result = subprocess.Popen(['ping', 'www.baidu.com' ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
# 獲取輸出
stdout, stderr = result.communicate()
print(1, stdout)
print(2, stderr)
# 檢查返回碼
print("返回碼:", result.returncode)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
輸出結果
F:\work\python\venv\devops\python.exe F:\work\python\project\gitlab\test.py
1
正在 Ping www.a.shifen.com [110.242.68.3] 具有 32 位元組的資料:
來自 110.242.68.3 的回覆: 位元組=32 時間=12ms TTL=53
來自 110.242.68.3 的回覆: 位元組=32 時間=11ms TTL=53
來自 110.242.68.3 的回覆: 位元組=32 時間=11ms TTL=53
來自 110.242.68.3 的回覆: 位元組=32 時間=10ms TTL=53
110.242.68.3 的 Ping 統計資訊:
資料包: 已傳送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計時間(以毫秒為單位):
最短 = 10ms,最長 = 12ms,平均 = 11ms
2
返回碼: 0
程序已結束,退出程式碼0
subprocess.call()
在 Python 3.5 之後建議使用 run().
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)
用途:執行由 args 所描述的命令。 等待命令完成,然後返回 returncode 屬性。
引數:
args:一個字串列表或字串,代表要執行的命令和引數。
stdin, stdout, stderr:可選引數,用於指定子程序的標準輸入、輸出和錯誤輸出。可以是檔案物件、PIPE(用於與父程序通訊)或其他合法的引數。如果不指定,通常使用預設值。
shell:一個布林值,預設為 False。如果設定為 True,則命令將在 shell 中執行,這可能會帶來安全風險(因為可能受到命令注入攻擊)。通常不建議使用 shell=True。
cwd:可選引數,指定子程序的當前工作目錄。
timeout:可選引數,設定命令執行的最大時間(秒)。如果超過這個時間,子程序會被殺死。
**other_popen_kwargs:其他可選的關鍵字引數,用於傳遞給底層的 Popen 類。
示例
import subprocess
process = subprocess.call(['ping', 'www.baidu.com'], stdout=subprocess.DEVNULL)
print(process) # 輸出: 0
subprocess.check_call()
在 Python 3.5 之後建議使用 run().
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)
用途:附帶引數執行命令。 等待命令完成。 如果返回碼為零則正常返回,否則引發 CalledProcessError。 CalledProcessError 物件將在 returncode 屬性中儲存返回碼。
引數:
args: 一個字串列表,表示要執行的命令及其引數。例如:['ls', '-l']。這是必需的引數。
stdin, stdout, stderr: 這些引數用於指定子程序的標準輸入、標準輸出和標準錯誤輸出。它們可以是 subprocess.PIPE(用於捕獲輸出),也可以是檔案物件(用於重定向輸出到檔案)。如果不指定這些引數,子程序將繼承父程序的標準輸入、輸出和錯誤流。
shell: 一個布林值,指示是否透過 shell 執行命令。預設為 False。如果設定為 True,則命令會由 shell 解析,這可能會帶來安全風險(因為可能受到命令注入攻擊)。通常不建議使用此引數,除非確實需要 shell 功能(如使用管道或重定向)。
cwd: 一個字串,指定子程序的當前工作目錄。預設為當前工作目錄。
timeout: 一個浮點數,指定命令執行的最長時間(秒)。如果命令執行時間超過這個時間,子程序會被終止。這是一個可選引數。
**other_popen_kwargs: 其他可以傳遞給 Popen 建構函式的引數。這些引數允許你自定義子程序的建立和行為。
示例
import subprocess
process = subprocess.check_call(['ping', 'www.baidu.com'], stdout=subprocess.DEVNULL)
print(process) # 輸出: 0
subprocess.check_output()
在 Python 3.5 之後建議使用 run().
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None, **other_popen_kwargs)
用途:附帶引數執行命令並返回其輸出。
引數:
args:一個字串列表,表示要執行的命令及其引數。例如:['ls', '-l']。
stdin:可選引數,用於指定子程序的標準輸入。通常不需要設定。
stderr:可選引數,用於指定子程序的錯誤輸出。預設不捕獲錯誤輸出。
shell:布林值,指示是否透過 shell 執行命令。預設為 False。設定為 True 時需注意安全風險,因為可能受到命令注入攻擊。
cwd:可選引數,指定子程序的當前工作目錄。
encoding:可選引數,用於指定輸出字串的編碼方式。如果不指定,輸出將是位元組串。
errors:可選引數,指定處理編碼錯誤的策略。
universal_newlines:(不推薦使用,建議使用 text 引數)如果為 True,則輸出將是文字模式,與 encoding 引數配合使用。
timeout:可選引數,指定命令執行的最長時間(秒)。超過這個時間會終止程序並丟擲異常。
text:布林值,指示是否以文字模式啟動子程序(建議使用這個引數替代 universal_newlines)。
**other_popen_kwargs:其他可選的關鍵字引數,用於傳遞給底層的 Popen 類。
示例
import subprocess
process = subprocess.check_output(['ping', 'www.baidu.com'], text=True)
print(process)
輸出結果
正在 Ping www.a.shifen.com [110.242.68.4] 具有 32 位元組的資料:
來自 110.242.68.4 的回覆: 位元組=32 時間=19ms TTL=53
來自 110.242.68.4 的回覆: 位元組=32 時間=12ms TTL=53
來自 110.242.68.4 的回覆: 位元組=32 時間=14ms TTL=53
來自 110.242.68.4 的回覆: 位元組=32 時間=22ms TTL=53
110.242.68.4 的 Ping 統計資訊:
資料包: 已傳送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計時間(以毫秒為單位):
最短 = 12ms,最長 = 22ms,平均 = 16ms
參考文件
https://docs.python.org/3/library/subprocess.html