python?subprocess.run()、subprocess.Popen()、subprocess.check_output()
Python的subprocess模塊是用于創(chuàng)建和管理子進程的模塊。它提供了一種在Python中調(diào)用外部命令的方式,可以執(zhí)行系統(tǒng)命令、啟動新的進程、連接到子進程的輸入/輸出管道等。
基本函數(shù)
subprocess.run
subprocess.run(args, *, stdin=None, input=None, stdout=None,
stderr=None, capture_output=False, text=None,
check=False, timeout=None, encoding=None, errors=None)
- 運行指定的命令,并等待其完成。args參數(shù)是一個字符串或列表,表示要執(zhí)行的命令和參數(shù)。
- stdin、stdout和stderr參數(shù)分別用于指定子進程的標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出的處理方式。
- capture_output參數(shù)用于指定是否捕獲子進程的輸出。
- check參數(shù)用于指定是否檢查子進程的返回值,如果返回值不為0,則會拋出CalledProcessError異常。
- timeout參數(shù)用于指定子進程的超時時間。
- encoding和errors參數(shù)用于指定輸入/輸出的編碼方式和錯誤處理方式。
示例(只可以捕獲標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯誤不知道咋獲取,異常也沒拋。。。以后再看,現(xiàn)在有事)
import subprocess
def execute_update_ip_sh(ip):
"""
執(zhí)行修改配置文件 ip 腳本,將會修改ky_ai_solution.json、nginx.conf、vsftpd.conf 等文件中的ip
"""
try:
# 構(gòu)建命令
command = ['/ky/update_ip.sh', ip]
# 執(zhí)行命令并獲取輸出(這個出錯直接就拋異常了,不能捕獲標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤)
# result = subprocess.check_output(command, universal_newlines=True)
result = subprocess.run(command, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, universal_newlines=True)
# 打印腳本的輸出
print(f"[{command}] 標(biāo)準(zhǔn)輸出:", result.stdout)
# 打印腳本的錯誤輸出(打印不出來)
print(f"[{command}] 標(biāo)準(zhǔn)錯誤輸出:", result.stderr)
# 執(zhí)行成功,返回True
return result.returncode == 0
# except subprocess.CalledProcessError as e:
except Exception as e:
# 執(zhí)行失敗,返回False
print(e)
print("ddddddddddddddddddddddddddddddddddddddd")
return False
if __name__ == "__main__":
execute_update_ip_sh("192.168.1.140")

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=False, startupinfo=None,
creationflags=0, restore_signals=True,
start_new_session=False, pass_fds=(), *,
encoding=None, errors=None)
- 啟動一個新的進程,并返回一個Popen對象,可以用于與子進程進行交互。
- args參數(shù)和其他參數(shù)的含義與subprocess.run()函數(shù)相同。
subprocess.Popen參數(shù)解釋
- -
args:要執(zhí)行的命令及其參數(shù)。可以是一個字符串或一個字符串列表。 - -
bufsize:指定緩沖區(qū)的大小。默認(rèn)值為-1,表示使用系統(tǒng)默認(rèn)的緩沖區(qū)大小。 - -
executable:指定要執(zhí)行的可執(zhí)行文件的路徑。默認(rèn)值為None,表示使用系統(tǒng)默認(rèn)的可執(zhí)行文件。 - -
stdin:指定子進程的標(biāo)準(zhǔn)輸入??梢允且粋€文件對象或一個文件描述符。默認(rèn)值為None,表示使用父進程的標(biāo)準(zhǔn)輸入。 - -
stdout:指定子進程的標(biāo)準(zhǔn)輸出??梢允且粋€文件對象或一個文件描述符。默認(rèn)值為None,表示使用父進程的標(biāo)準(zhǔn)輸出。 - -
stderr:指定子進程的標(biāo)準(zhǔn)錯誤輸出??梢允且粋€文件對象或一個文件描述符。默認(rèn)值為None,表示使用父進程的標(biāo)準(zhǔn)錯誤輸出。 - -
preexec_fn:在子進程執(zhí)行前調(diào)用的可調(diào)用對象。默認(rèn)值為None,表示不調(diào)用任何函數(shù)。
示例:使用preexec_fn來將Popen對象綁定進程組
當(dāng)使用shell=True時,subprocess.Popen()函數(shù)創(chuàng)建的子進程實際上是一個shell進程,而不是直接執(zhí)行的命令。因此,向Popen對象發(fā)送信號并不能直接影響到子進程。
如果需要向通過shell執(zhí)行的命令發(fā)送信號,可以使用os.killpg()函數(shù)來發(fā)送信號給進程組。具體步驟如下:
- 創(chuàng)建
Popen對象時,設(shè)置preexec_fn=os.setsid,以創(chuàng)建一個新的進程組。 - 使用
os.killpg()函數(shù)發(fā)送信號給進程組。
下面是一個示例,演示了如何向通過shell執(zhí)行的命令發(fā)送信號:
import subprocess
import os
import signal
# 通過shell執(zhí)行命令
process = subprocess.Popen('sleep 10', shell=True, preexec_fn=os.setsid)
# 發(fā)送信號給進程組
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
在這個示例中,首先通過subprocess.Popen()函數(shù)創(chuàng)建了一個通過shell執(zhí)行的命令。在創(chuàng)建Popen對象時,通過preexec_fn=os.setsid設(shè)置了preexec_fn參數(shù),以創(chuàng)建一個新的進程組。
然后,使用os.killpg()函數(shù)發(fā)送信號給進程組。在這個示例中,發(fā)送了SIGTERM信號,即終止信號。
需要注意的是,向進程組發(fā)送信號會影響到進程組中的所有進程。因此,如果有多個通過shell執(zhí)行的命令,它們都屬于同一個進程組,發(fā)送信號時需要注意。
- -
close_fds:指定是否在子進程中關(guān)閉父進程中打開的文件描述符。默認(rèn)值為True,表示關(guān)閉文件描述符。 - -
shell:指定是否通過shell來執(zhí)行命令。默認(rèn)值為False,表示不通過shell執(zhí)行命令。
當(dāng)shell參數(shù)設(shè)置為True時,表示通過shell來執(zhí)行命令。這意味著可以使用shell的語法和功能,比如管道、重定向、通配符等。在這種情況下,args參數(shù)可以是一個字符串,表示要執(zhí)行的完整命令。
當(dāng)shell參數(shù)設(shè)置為False時,表示不通過shell來執(zhí)行命令。這是默認(rèn)的行為。在這種情況下,args參數(shù)應(yīng)該是一個字符串列表,其中第一個元素是要執(zhí)行的命令,后續(xù)元素是命令的參數(shù)。
需要注意的是,使用shell=True時,應(yīng)該謹(jǐn)慎處理輸入?yún)?shù),避免命令注入等安全問題。應(yīng)該始終對用戶輸入進行驗證和過濾,避免直接將用戶輸入拼接到命令中。
下面是一個示例,演示了shell參數(shù)的用法:
import subprocess
# 通過shell執(zhí)行命令
subprocess.Popen('ls -l', shell=True)
# 不通過shell執(zhí)行命令
subprocess.Popen(['ls', '-l'])
在這個示例中,第一個Popen()函數(shù)調(diào)用通過shell執(zhí)行了ls -l命令,而第二個Popen()函數(shù)調(diào)用不通過shell執(zhí)行了ls -l命令。
使用shell執(zhí)行和不使用shell執(zhí)行的差異(以管道為例)
使用shell執(zhí)行:
下面是一個示例,演示了如何通過shell執(zhí)行命令并使用管道:
import subprocess
# 通過shell執(zhí)行命令并使用管道
process = subprocess.Popen('ls -l | grep .txt', shell=True)
# 等待子進程結(jié)束
process.wait()
在這個示例中,通過subprocess.Popen()函數(shù)的shell參數(shù)設(shè)置為True,表示通過shell執(zhí)行命令。然后,可以使用shell的管道語法|將兩個命令連接起來,實現(xiàn)輸出過濾。
不使用shell執(zhí)行:
import subprocess # 不通過shell執(zhí)行命令并使用管道 command1 = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE) command2 = subprocess.Popen(['grep', '.txt'], stdin=command1.stdout, stdout=subprocess.PIPE) # 獲取命令2的輸出 output = command2.communicate()[0] # 打印輸出結(jié)果 print(output.decode())
在這個示例中,首先創(chuàng)建了兩個Popen()對象,分別對應(yīng)兩個命令。command1執(zhí)行了ls -l命令,并將輸出通過管道傳遞給command2。command2執(zhí)行了grep .txt命令,并將結(jié)果輸出到標(biāo)準(zhǔn)輸出。
通過command2.communicate()方法獲取命令2的輸出,并將其打印出來。
不通過shell執(zhí)行命令時,需要手動設(shè)置命令之間的輸入輸出關(guān)系,以及處理命令的輸出。這需要更多的代碼來實現(xiàn),但也提供了更多的靈活性和控制能力。
-
cwd:指定子進程的當(dāng)前工作目錄。默認(rèn)值為None,表示使用父進程的當(dāng)前工作目錄。-
env:指定子進程的環(huán)境變量??梢允且粋€字典,表示環(huán)境變量的鍵值對。默認(rèn)值為None,表示使用父進程的環(huán)境變量。-
universal_newlines:指定是否將輸入/輸出流以文本模式打開。默認(rèn)值為False,表示以二進制模式打開。-
startupinfo:指定子進程的啟動信息。可以是一個subprocess.STARTUPINFO對象,用于設(shè)置子進程的一些屬性。默認(rèn)值為None。-
creationflags:指定子進程的創(chuàng)建標(biāo)志。默認(rèn)值為0,表示使用默認(rèn)的創(chuàng)建標(biāo)志。-
restore_signals:指定是否在子進程中恢復(fù)信號處理程序。默認(rèn)值為True,表示恢復(fù)信號處理程序。-
start_new_session:指定是否在新的會話中啟動子進程。默認(rèn)值為False,表示在當(dāng)前會話中啟動子進程。-
pass_fds:指定要傳遞給子進程的文件描述符列表。默認(rèn)值為(),表示不傳遞文件描述符。-
encoding:指定輸入/輸出的編碼方式。默認(rèn)值為None,表示使用系統(tǒng)默認(rèn)的編碼方式。-
errors:指定輸入/輸出的錯誤處理方式。默認(rèn)值為None,表示使用系統(tǒng)默認(rèn)的錯誤處理方式。
總結(jié)
subprocess.Popen()函數(shù)會返回一個Popen對象,可以用于與子進程進行交互。Popen對象具有一些常用的方法和屬性,比如communicate()、wait()、poll()、terminate()、kill()、stdout、stderr和returncode等。
Popen對象的常用方法和屬性
- communicate(input=None, timeout=None):與子進程進行交互,發(fā)送輸入并獲取輸出。
- wait():等待子進程結(jié)束,并返回其返回值。
- poll():檢查子進程是否結(jié)束,如果結(jié)束則返回其返回值,否則返回None。
- terminate():終止子進程。
- kill():殺死子進程。
- stdout:子進程的標(biāo)準(zhǔn)輸出。
- stderr:子進程的標(biāo)準(zhǔn)錯誤輸出。
- returncode:子進程的返回值。
下面是一個使用subprocess模塊的示例,演示了如何執(zhí)行一個系統(tǒng)命令并獲取其輸出:
import subprocess # 執(zhí)行系統(tǒng)命令 result = subprocess.run(['ls', '-l'], capture_output=True, text=True) # 獲取命令的輸出 output = result.stdout print(output)
以上代碼會執(zhí)行ls -l命令,并將其輸出打印出來。
需要注意的是,subprocess模塊在執(zhí)行外部命令時,存在一定的安全風(fēng)險,特別是在使用shell=True參數(shù)時。因此,在使用subprocess模塊時,應(yīng)該謹(jǐn)慎處理輸入?yún)?shù),避免命令注入等安全問題。
subprocess.check_output
subprocess.check_output函數(shù)是Python標(biāo)準(zhǔn)庫subprocess模塊中的一個函數(shù),用于執(zhí)行系統(tǒng)命令并返回命令的輸出結(jié)果。
它的用法是:
subprocess.check_output(args, *, stdin=None, stderr=None,
shell=False, universal_newlines=False)
其中,args是一個字符串或者字符串列表,表示要執(zhí)行的命令及其參數(shù)。stdin、stderr、shell和universal_newlines是可選參數(shù),用于控制輸入、錯誤輸出、是否使用shell以及輸出結(jié)果的編碼方式。
check_output函數(shù)會執(zhí)行指定的命令,并等待命令執(zhí)行完成。如果命令執(zhí)行成功,它會返回命令的輸出結(jié)果(以字節(jié)字符串的形式),如果命令執(zhí)行失敗,它會拋出一個CalledProcessError異常。
在上述代碼中,subprocess.check_output函數(shù)被用于執(zhí)行一些系統(tǒng)命令,如ip addr show和ip route show,以獲取當(dāng)前以太網(wǎng)接口的IP配置信息。
到此這篇關(guān)于python subprocess.run()、subprocess.Popen()、subprocess.check_output()的文章就介紹到這了,更多相關(guān)python subprocess 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用python 實現(xiàn)在不確定行數(shù)情況下多行輸入方法
今天小編就為大家分享一篇用python 實現(xiàn)在不確定行數(shù)情況下多行輸入方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-01-01

