如何使用python的subprocess執(zhí)行命令、交互、等待、是否結(jié)束及解析JSON結(jié)果
前言
Python的subprocess模塊提供了一種在Python中調(diào)用外部命令的方法。它允許您在Python程序中啟動(dòng)新進(jìn)程,連接到它們的輸入/輸出/錯(cuò)誤管道,并等待它們完成。
常用用法
下面是一些subprocess模塊的常用用法:
- 運(yùn)行外部命令并獲取輸出:
import subprocess output = subprocess.check_output(["ls", "-l"]) print(output.decode())
- 運(yùn)行外部命令并獲取返回值:
import subprocess return_code = subprocess.call(["ls", "-l"]) print(return_code)
- 運(yùn)行外部命令并將輸出重定向到文件:
import subprocess
with open("output.txt", "w") as f:
subprocess.call(["ls", "-l"], stdout=f)
- 運(yùn)行外部命令并將輸入從文件中讀?。?/li>
import subprocess
with open("input.txt", "r") as f:
subprocess.call(["grep", "hello"], stdin=f)
- 運(yùn)行外部命令并將輸入從Python程序中提供:
import subprocess subprocess.call(["grep", "hello"], input=b"hello world ")
- 運(yùn)行外部命令并捕獲標(biāo)準(zhǔn)錯(cuò)誤:
import subprocess
try:
subprocess.check_output(["ls", "-l", "/nonexistent"])
except subprocess.CalledProcessError as e:
print(e.stderr.decode())
- 運(yùn)行外部命令并等待它完成:
import subprocess
p = subprocess.Popen(["sleep", "5"])
p.wait()
print("Done")
以上是subprocess模塊的一些常用用法,更多詳細(xì)信息請(qǐng)參考Python官方文檔。
創(chuàng)建一個(gè)新的進(jìn)程
Python的subprocess模塊中的Popen函數(shù)用于創(chuàng)建一個(gè)新的進(jìn)程,并與其進(jìn)行交互。Popen函數(shù)的語法如下:
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)
參數(shù)說明:
- args:要執(zhí)行的命令,可以是一個(gè)字符串或一個(gè)列表。如果是一個(gè)字符串,則會(huì)被解釋為一個(gè)shell命令;如果是一個(gè)列表,則第一個(gè)元素是要執(zhí)行的命令,后面的元素是命令的參數(shù)。
- bufsize:緩沖區(qū)大小,默認(rèn)為-1,表示使用系統(tǒng)默認(rèn)值。
- executable:要執(zhí)行的可執(zhí)行文件的路徑,默認(rèn)為None,表示使用系統(tǒng)默認(rèn)的可執(zhí)行文件。
- stdin、stdout、stderr:分別表示標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤輸出的文件描述符。默認(rèn)為None,表示使用父進(jìn)程的標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤輸出。
- preexec_fn:在子進(jìn)程執(zhí)行前被調(diào)用的可執(zhí)行對(duì)象,可以是一個(gè)函數(shù)或一個(gè)可調(diào)用對(duì)象。默認(rèn)為None。
- close_fds:如果為True,則在子進(jìn)程中關(guān)閉所有文件描述符。默認(rèn)為True。
- shell:如果為True,則將args作為一個(gè)shell命令執(zhí)行。默認(rèn)為False。
- cwd:子進(jìn)程的當(dāng)前工作目錄。默認(rèn)為None,表示使用父進(jìn)程的當(dāng)前工作目錄。
- env:子進(jìn)程的環(huán)境變量。默認(rèn)為None,表示使用父進(jìn)程的環(huán)境變量。
- universal_newlines:如果為True,則將stdin、stdout、stderr的數(shù)據(jù)以文本模式處理。默認(rèn)為False。
- startupinfo:用于指定子進(jìn)程的一些啟動(dòng)信息,如窗口大小、標(biāo)題等。默認(rèn)為None。
- creationflags:用于指定子進(jìn)程的一些標(biāo)志,如CREATE_NEW_CONSOLE、CREATE_NEW_PROCESS_GROUP等。默認(rèn)為0。
Popen函數(shù)返回一個(gè)Popen對(duì)象,可以通過該對(duì)象的方法和屬性與子進(jìn)程進(jìn)行交互,如:
- communicate(input=None, timeout=None):與子進(jìn)程進(jìn)行交互,發(fā)送input數(shù)據(jù)并等待子進(jìn)程執(zhí)行完畢。如果timeout不為None,則在指定時(shí)間內(nèi)等待子進(jìn)程執(zhí)行完畢。
- poll():檢查子進(jìn)程是否已經(jīng)結(jié)束,如果已經(jīng)結(jié)束則返回子進(jìn)程的退出狀態(tài)碼,否則返回None。
- wait(timeout=None):等待子進(jìn)程執(zhí)行完畢,并返回子進(jìn)程的退出狀態(tài)碼。如果timeout不為None,則在指定時(shí)間內(nèi)等待子進(jìn)程執(zhí)行完畢。
- send_signal(signal):向子進(jìn)程發(fā)送信號(hào)。
- terminate():向子進(jìn)程發(fā)送SIGTERM信號(hào),終止子進(jìn)程。
- kill():向子進(jìn)程發(fā)送SIGKILL信號(hào),強(qiáng)制終止子進(jìn)程。
- pid:子進(jìn)程的進(jìn)程ID。
- returncode:子進(jìn)程的退出狀態(tài)碼。
示例代碼:
import subprocess
# 執(zhí)行一個(gè)簡(jiǎn)單的命令
p = subprocess.Popen('ls -l', shell=True)
p.wait()
# 執(zhí)行一個(gè)帶參數(shù)的命令
p = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
output, error = p.communicate()
print(output.decode())
# 執(zhí)行一個(gè)長(zhǎng)時(shí)間運(yùn)行的命令,并在指定時(shí)間內(nèi)等待其執(zhí)行完畢
p = subprocess.Popen('sleep 10', shell=True)
try:
p.wait(timeout=5)
except subprocess.TimeoutExpired:
p.kill()
與子進(jìn)程進(jìn)行交互
communicate()是subprocess模塊中的一個(gè)方法,用于與子進(jìn)程進(jìn)行交互。它會(huì)向子進(jìn)程的標(biāo)準(zhǔn)輸入發(fā)送數(shù)據(jù),并等待子進(jìn)程完成任務(wù)后獲取其標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出。
communicate()方法的語法如下:
stdout, stderr = subprocess.communicate(input=None, timeout=None)
其中,input參數(shù)是要發(fā)送給子進(jìn)程的數(shù)據(jù),可以是字符串或字節(jié)流。如果不需要向子進(jìn)程發(fā)送數(shù)據(jù),則可以將其設(shè)置為None。timeout參數(shù)是等待子進(jìn)程完成任務(wù)的超時(shí)時(shí)間,單位為秒。如果子進(jìn)程在超時(shí)時(shí)間內(nèi)未完成任務(wù),則會(huì)拋出TimeoutExpired異常。
communicate()方法會(huì)返回一個(gè)元組,其中第一個(gè)元素是子進(jìn)程的標(biāo)準(zhǔn)輸出,第二個(gè)元素是子進(jìn)程的標(biāo)準(zhǔn)錯(cuò)誤輸出。如果子進(jìn)程沒有輸出,則對(duì)應(yīng)的元素為None。
下面是一個(gè)使用communicate()方法的示例:
import subprocess
# 執(zhí)行命令
p = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 獲取子進(jìn)程的輸出
stdout, stderr = p.communicate()
# 輸出子進(jìn)程的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出
print(stdout.decode('utf-8'))
print(stderr.decode('utf-8'))
在上面的示例中,我們使用Popen()方法創(chuàng)建了一個(gè)子進(jìn)程,并將其標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出分別重定向到管道中。然后,我們使用communicate()方法等待子進(jìn)程完成任務(wù),并獲取其標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出。最后,我們將其轉(zhuǎn)換為字符串并輸出。
執(zhí)行結(jié)果解析成json格式
可以使用Python的json模塊將subprocess執(zhí)行結(jié)果解析成json格式。
假設(shè)subprocess執(zhí)行的命令是獲取系統(tǒng)信息的命令,如下所示:
import subprocess cmd = "systeminfo" result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
執(zhí)行結(jié)果保存在result變量中,可以使用json模塊將其解析成json格式,如下所示:
import json
output = result.stdout.decode('utf-8')
json_output = json.loads(output)
其中,result.stdout是subprocess執(zhí)行結(jié)果的標(biāo)準(zhǔn)輸出,使用decode方法將其轉(zhuǎn)換成字符串類型。然后使用json.loads方法將字符串解析成json格式。
解析后的json格式可以按照需要進(jìn)行處理和使用。
檢查子進(jìn)程是否已經(jīng)結(jié)束
在subprocess中,poll()方法用于檢查子進(jìn)程是否已經(jīng)結(jié)束。如果子進(jìn)程已經(jīng)結(jié)束,poll()方法會(huì)返回子進(jìn)程的退出狀態(tài)碼。如果子進(jìn)程還在運(yùn)行,poll()方法會(huì)返回None。
下面是一個(gè)使用poll()方法的示例:
import subprocess
# 啟動(dòng)子進(jìn)程
p = subprocess.Popen(['ls', '-l'])
# 檢查子進(jìn)程是否已經(jīng)結(jié)束
while p.poll() is None:
print('子進(jìn)程還在運(yùn)行...')
# 子進(jìn)程已經(jīng)結(jié)束,獲取退出狀態(tài)碼
print('子進(jìn)程已經(jīng)結(jié)束,退出狀態(tài)碼為:', p.returncode)
在上面的示例中,我們啟動(dòng)了一個(gè)子進(jìn)程來執(zhí)行l(wèi)s命令,然后使用poll()方法檢查子進(jìn)程是否已經(jīng)結(jié)束。如果子進(jìn)程還在運(yùn)行,就會(huì)一直輸出“子進(jìn)程還在運(yùn)行…”,直到子進(jìn)程結(jié)束。當(dāng)子進(jìn)程結(jié)束后,我們使用returncode屬性獲取子進(jìn)程的退出狀態(tài)碼,并輸出到控制臺(tái)。
等待子進(jìn)程結(jié)束
在subprocess模塊中,wait()方法用于等待子進(jìn)程結(jié)束并返回狀態(tài)碼。它會(huì)阻塞當(dāng)前進(jìn)程,直到子進(jìn)程結(jié)束為止。
wait()方法的語法如下:
status = subprocess.Popen.wait(self, timeout=None, endtime=None)
其中,timeout參數(shù)表示等待子進(jìn)程結(jié)束的最長(zhǎng)時(shí)間,單位為秒;endtime參數(shù)表示等待子進(jìn)程結(jié)束的最晚時(shí)間,是一個(gè)時(shí)間戳。
如果子進(jìn)程已經(jīng)結(jié)束,wait()方法會(huì)立即返回狀態(tài)碼;如果子進(jìn)程還在運(yùn)行,wait()方法會(huì)阻塞當(dāng)前進(jìn)程,直到子進(jìn)程結(jié)束為止。
wait()方法返回的狀態(tài)碼是一個(gè)整數(shù),表示子進(jìn)程的退出狀態(tài)。如果子進(jìn)程正常結(jié)束,狀態(tài)碼為0;如果子進(jìn)程異常結(jié)束,狀態(tài)碼為一個(gè)非零值,具體的值表示異常的類型。
判斷是否執(zhí)行成功
在Python中,可以使用subprocess模塊的returncode屬性來判斷子進(jìn)程是否執(zhí)行成功。如果子進(jìn)程成功執(zhí)行,returncode屬性的值為0;如果子進(jìn)程執(zhí)行失敗,returncode屬性的值為非零??梢酝ㄟ^以下代碼來實(shí)現(xiàn):
import subprocess
# 執(zhí)行命令
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 判斷是否執(zhí)行成功
if result.returncode == 0:
print('執(zhí)行成功')
else:
print('執(zhí)行失敗')
在上面的代碼中,我們使用subprocess.run()方法執(zhí)行了一個(gè)ls -l命令,并將結(jié)果保存在result變量中。然后,我們通過判斷result.returncode的值來判斷子進(jìn)程是否執(zhí)行成功。如果returncode的值為0,則表示執(zhí)行成功;否則,表示執(zhí)行失敗。
總結(jié)
到此這篇關(guān)于如何使用python的subprocess執(zhí)行命令、交互、等待、是否結(jié)束及解析JSON結(jié)果的文章就介紹到這了,更多相關(guān)python subprocess模塊用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pandas中DataFrame的分組/分割/合并的實(shí)現(xiàn)
這篇文章主要介紹了Pandas中DataFrame的分組/分割/合并的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
python自動(dòng)重試第三方包retrying模塊的方法
retrying是一個(gè)python的重試包,可以用來自動(dòng)重試一些可能運(yùn)行失敗的程序段。這篇文章主要介紹了python自動(dòng)重試第三方包retrying的方法,需要的朋友參考下吧2018-04-04
爬山算法簡(jiǎn)介和Python實(shí)現(xiàn)實(shí)例
這篇文章主要介紹了爬山算法,爬山法(climbing method)是一種優(yōu)化算法,其一般從一個(gè)隨機(jī)的解開始,然后逐步找到一個(gè)最優(yōu)解(局部最優(yōu))然后用Python實(shí)現(xiàn)了這個(gè)算法,需要的朋友可以參考下2014-04-04
python GUI庫圖形界面開發(fā)之PyQt5瀏覽器控件QWebEngineView詳細(xì)使用方法
這篇文章主要介紹了python GUI庫圖形界面開發(fā)之PyQt5瀏覽器控件QWebEngineView詳細(xì)使用方法,需要的朋友可以參考下2020-02-02
Python實(shí)現(xiàn)雙軸組合圖表柱狀圖和折線圖的具體流程
這篇文章主要介紹了Python雙軸組合圖表柱狀圖+折線圖,Python繪制雙軸組合的關(guān)鍵在plt庫的twinx()函數(shù),具體實(shí)例代碼跟隨小編一起看看吧2021-08-08
Python中的文件和目錄操作實(shí)現(xiàn)代碼
對(duì)于文件和目錄的處理,雖然可以通過操作系統(tǒng)命令來完成,但是Python語言為了便于開發(fā)人員以編程的方式處理相關(guān)工作,提供了許多處理文件和目錄的內(nèi)置函數(shù)。重要的是,這些函數(shù)無論是在Unix、Windows還是Macintosh平臺(tái)上,它們的使用方式是完全一致的。2011-03-03

