python Subprocess 模組

小吉猫發表於2024-07-24

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

相關文章