如何使用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)行外部命令并將輸入從文件中讀取:
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ù)的語(yǔ)法如下:
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ù)說(shuō)明:
- 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ì)象,可以通過(guò)該對(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()
方法的語(yǔ)法如下:
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)程沒(méi)有輸出,則對(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)程來(lái)執(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()方法的語(yǔ)法如下:
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屬性來(lái)判斷子進(jìn)程是否執(zhí)行成功。如果子進(jìn)程成功執(zhí)行,returncode屬性的值為0;如果子進(jìn)程執(zhí)行失敗,returncode屬性的值為非零??梢酝ㄟ^(guò)以下代碼來(lái)實(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變量中。然后,我們通過(guò)判斷result.returncode的值來(lái)判斷子進(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),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07python自動(dòng)重試第三方包retrying模塊的方法
retrying是一個(gè)python的重試包,可以用來(lái)自動(dòng)重試一些可能運(yùn)行失敗的程序段。這篇文章主要介紹了python自動(dòng)重試第三方包retrying的方法,需要的朋友參考下吧2018-04-04爬山算法簡(jiǎn)介和Python實(shí)現(xiàn)實(shí)例
這篇文章主要介紹了爬山算法,爬山法(climbing method)是一種優(yōu)化算法,其一般從一個(gè)隨機(jī)的解開(kāi)始,然后逐步找到一個(gè)最優(yōu)解(局部最優(yōu))然后用Python實(shí)現(xiàn)了這個(gè)算法,需要的朋友可以參考下2014-04-04python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5瀏覽器控件QWebEngineView詳細(xì)使用方法
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5瀏覽器控件QWebEngineView詳細(xì)使用方法,需要的朋友可以參考下2020-02-02Python實(shí)現(xiàn)雙軸組合圖表柱狀圖和折線圖的具體流程
這篇文章主要介紹了Python雙軸組合圖表柱狀圖+折線圖,Python繪制雙軸組合的關(guān)鍵在plt庫(kù)的twinx()函數(shù),具體實(shí)例代碼跟隨小編一起看看吧2021-08-08Python中的文件和目錄操作實(shí)現(xiàn)代碼
對(duì)于文件和目錄的處理,雖然可以通過(guò)操作系統(tǒng)命令來(lái)完成,但是Python語(yǔ)言為了便于開(kāi)發(fā)人員以編程的方式處理相關(guān)工作,提供了許多處理文件和目錄的內(nèi)置函數(shù)。重要的是,這些函數(shù)無(wú)論是在Unix、Windows還是Macintosh平臺(tái)上,它們的使用方式是完全一致的。2011-03-03