已經(jīng)知道,os.system可以方便的利用python代碼執(zhí)行一些像ping、ipconfig之類(lèi)的系統(tǒng)命令,但卻只能得到命令執(zhí)行是否成功,不能獲得命令成功執(zhí)行后的結(jié)果,像下面這樣:
>>> s = os.system("ping www.baidu.com")
正在 Ping www.a.shifen.com [220.181.38.150] 具有 32 字節(jié)的數(shù)據(jù):
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=18ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=19ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=23ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=22ms TTL=52
220.181.38.150 的 Ping 統(tǒng)計(jì)信息:
數(shù)據(jù)包: 已發(fā)送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計(jì)時(shí)間(以毫秒為單位):
最短 = 18ms,最長(zhǎng) = 23ms,平均 = 20ms
>>> s
0
>>> type(s)
<class 'int'>
>>>
在上面的代碼中,利用os.system執(zhí)行“ping www.baidu.com”并把結(jié)果賦值給s,但在下面可以看到,s的內(nèi)容是int類(lèi)型的0(表示命令執(zhí)行成功),并不是命令的執(zhí)行結(jié)果。如果只是需要判斷命令是否執(zhí)行成功,那完全可以使用這種方法,但如果想要獲取命令執(zhí)行的結(jié)果呢?可以使用subprocess這個(gè)模塊。
一:subprocess的作用
subprocess模塊主要用于創(chuàng)建子進(jìn)程,并連接它們的輸入、輸出和錯(cuò)誤管道,獲取它們的返回狀態(tài)。通俗地說(shuō)就是通過(guò)這個(gè)模塊,你可以在Python的代碼里執(zhí)行操作系統(tǒng)級(jí)別的命令,比如“ipconfig”、“du -sh”等等。subprocess模塊替代了一些老的模塊和函數(shù),比如:
os.system
os.spawn*
subprocess過(guò)去版本中的call(),check_call()和check_output()已經(jīng)被run()方法取代了。run()方法為3.5版本新增。大多數(shù)情況下,推薦使用run()方法調(diào)用子進(jìn)程,執(zhí)行操作系統(tǒng)命令。在更高級(jí)的使用場(chǎng)景,你還可以使用Popen接口。其實(shí)run()方法在底層調(diào)用的就是Popen接口。
二:subprocess的run方法
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, encoding=None, errors=None)
功能:執(zhí)行args參數(shù)所表示的命令,等待命令結(jié)束,并返回一個(gè)CompletedProcess類(lèi)型對(duì)象。
下面是run參數(shù)的作用:
-
args:表示要執(zhí)行的命令。必須是一個(gè)字符串,字符串參數(shù)列表。
-
stdin、stdout和stderr:子進(jìn)程的標(biāo)準(zhǔn)輸入、輸出和錯(cuò)誤。其值可以是subprocess.PIPE、subprocess.DEVNULL、一個(gè)已經(jīng)存在的文件描述符、已經(jīng)打開(kāi)的文件對(duì)象或者None。subprocess.PIPE表示為子進(jìn)程創(chuàng)建新的管道。subprocess.DEVNULL表示使用os.devnull。默認(rèn)使用的是None,表示什么都不做。另外,stderr可以合并到stdout里一起輸出。
-
timeout:設(shè)置命令超時(shí)時(shí)間。如果命令執(zhí)行時(shí)間超時(shí),子進(jìn)程將被殺死,并彈出TimeoutExpired異常。
-
check:如果該參數(shù)設(shè)置為T(mén)rue,并且進(jìn)程退出狀態(tài)碼不是0,則彈出CalledProcessError異常。
-
encoding:如果指定了該參數(shù),則stdin、stdout和stderr可以接收字符串?dāng)?shù)據(jù),并以該編碼方式編碼。否則只接收bytes類(lèi)型的數(shù)據(jù)。
-
shell:如果該參數(shù)為T(mén)rue,將通過(guò)操作系統(tǒng)的shell執(zhí)行指定的命令,如果執(zhí)行命令時(shí)遇見(jiàn)權(quán)限不足的境況,可以將此參數(shù)設(shè)置為T(mén)rue
注意,run()方法返回的不是我們想要的執(zhí)行結(jié)果或相關(guān)信息,而是一個(gè)CompletedProcess類(lèi)型對(duì)象。
>>> r = subprocess.run("ping www.baidu.com")
正在 Ping www.a.shifen.com [220.181.38.150] 具有 32 字節(jié)的數(shù)據(jù):
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=17ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=17ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=19ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=18ms TTL=52
220.181.38.150 的 Ping 統(tǒng)計(jì)信息:
數(shù)據(jù)包: 已發(fā)送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計(jì)時(shí)間(以毫秒為單位):
最短 = 17ms,最長(zhǎng) = 19ms,平均 = 17ms
>>> type(r)
<class 'subprocess.CompletedProcess'>
>>> r
CompletedProcess(args='ping www.baidu.com', returncode=0)
>>>
可以看到,run方法的執(zhí)行結(jié)果是一個(gè)CompletedProcess類(lèi)型對(duì)象。
下面是CompletedProcess類(lèi)型對(duì)象的一些屬性:
args 啟動(dòng)進(jìn)程的參數(shù),通常是個(gè)列表或字符串。
returncode 進(jìn)程結(jié)束狀態(tài)返回碼。0表示成功狀態(tài)。
stdout 獲取子進(jìn)程的stdout。通常為bytes類(lèi)型序列,None表示沒(méi)有捕獲值。如果你在調(diào)用run()方法時(shí),設(shè)置了參數(shù)stderr=subprocess.STDOUT,則錯(cuò)誤信息會(huì)和stdout一起輸出,此時(shí)stderr的值是None。
stderr() 獲取子進(jìn)程的錯(cuò)誤信息。通常為bytes類(lèi)型序列,None表示沒(méi)有捕獲值。
check_returncode() 用于檢查返回碼。如果返回狀態(tài)碼不為零,彈出CalledProcessError異常。
獲取狀態(tài)碼:
r = subprocess.run("ping www.baidu.com")
正在 Ping www.a.shifen.com [220.181.38.150] 具有 32 字節(jié)的數(shù)據(jù):
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=35ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=29ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=16ms TTL=52
來(lái)自 220.181.38.150 的回復(fù): 字節(jié)=32 時(shí)間=18ms TTL=52
220.181.38.150 的 Ping 統(tǒng)計(jì)信息:
數(shù)據(jù)包: 已發(fā)送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計(jì)時(shí)間(以毫秒為單位):
最短 = 16ms,最長(zhǎng) = 35ms,平均 = 24ms>>> r.returncode
0
獲取命令執(zhí)行后的內(nèi)容:
run()方法返回的是一個(gè)CompletedProcess類(lèi)型對(duì)象,不能直接獲取我們通常想要的結(jié)果。要獲取命令執(zhí)行的結(jié)果或者信息,在調(diào)用run()方法的時(shí)候,請(qǐng)指定stdout=subprocess.PIPE。
>>> ret = subprocess.run('dir', shell=True, stdout=subprocess.PIPE)
>>> ret
CompletedProcess(args='dir', returncode=0, stdout=b' \xc7\xfd\xb6\xaf\xc6\xf7 C \xd6\xd0\xb5\xc4\xbe\xed\xca\xc7 Windows 10\r\n \xbe\xed\xb5\xc4\xd0\xf2\xc1\xd0\xba\xc5\xca\xc7 02DE-BFF0\r\n\r\n C:\\Users\\lwy \xb5\xc4\xc4\xbf\xc2\xbc\r\n\r\n2019/12/31 10:29 <DIR> .\r\n2019/12/31 10:29 <DIR> ..\r\n2019/10/16 10:27 <DIR> .3T\r\n2019/09/23 20:31 <DIR> .anaconda\r\n2019/10/07 13:14 <DIR> .android\r\n2019/07/23 09:54 <DIR> .astropy\r\n2019/12/28 19:01 4,807 .bash_history\r\n2019/09/26 18:19 <DIR> .conda\r\n2019/09/26 18:19 151 .condarc\r\n2019/10/07 10:18 <DIR> .config\r\n2019/11/02 11:50 1,126 .dbshell\r\n2019/07/31 16:49 181 .gitconfig\r\n2019/07/22 20:31 <DIR> .ipython\r\n2019/09/23 16:15 <DIR> .keras\r\n2019/11/06 21:47 <DIR> .matplotlib\r\n2019/08/01 09:36 37 .minttyrc\r\n2019/10/06 20:53 <DIR> .mitmproxy\r\n2019/10/01 15:20 0 .mongorc.js\r\n2019/08/30 15:19 <DIR> .oracle_jre_usage\r\n2019/07/21 23:57 <DIR> .PyCharm2019.1\r\n2019/12/10 17:04 25 .python_history\r\n2019/07/31 16:04 <DIR> .rdm\r\n2019/07/31 16:38 35 .rediscli_history\r\n2019/07/22 20:31 <DIR> .spyder-py3\r\n2019/09/17 17:51 5,339 .viminfo\r\n2019/12/12 13:21 <DIR> 3D Objects\r\n2019/12/12 13:21 <DIR> Contacts\r\n2019/12/31 13:41 <DIR> Desktop\r\n2019/12/18 15:47 <DIR> Documents\r\n2019/12/30 16:34 <DIR> Downloads\r\n2019/12/12 13:21 <DIR> Favorites\r\n2019/10/15 16:36 <DIR> Funshion\r\n2019/12/12 13:21 <DIR> Links\r\n2019/12/12 13:21 <DIR> Music\r\n2019/07/21 23:58 <DIR> OneDrive\r\n2019/12/12 13:21 <DIR> Pictures\r\n2019/12/12 13:21 <DIR> Saved Games\r\n2019/12/12 13:21 <DIR> Searches\r\n2019/12/31 10:27 <DIR> test22\r\n2019/12/12 13:21 <DIR> Videos\r\n 9 \xb8\xf6\xce\xc4\xbc\xfe 11,701 \xd7\xd6\xbd\xda\r\n 31 \xb8\xf6\xc4\xbf\xc2\xbc 51,676,090,368 \xbf\xc9\xd3\xc3\xd7\xd6\xbd\xda\r\n')
>>> type(ret)
<class 'subprocess.CompletedProcess'>
>>>
可以看到,這時(shí)候返回的內(nèi)容就是命令的執(zhí)行結(jié)果了,是一個(gè)CompletedProcess的類(lèi)型,也可以通過(guò)指定編碼使返回對(duì)象是一個(gè)字符串類(lèi)型。
>>> ret = subprocess.run('dir', shell=True, stdout=subprocess.PIPE).stdout.decode("gbk")
>>> ret
' 驅(qū)動(dòng)器 C 中的卷是 Windows 10\r\n 卷的序列號(hào)是 02DE-BFF0\r\n\r\n C:\\Users\\lwy 的目錄\r\n\r\n2019/12/31 10:29 <DIR> .\r\n2019/12/31 10:29 <DIR> ..\r\n2019/10/16 10:27 <DIR> .3T\r\n2019/09/23 20:31 <DIR> .anaconda\r\n2019/10/07 13:14 <DIR> .android\r\n2019/07/23 09:54 <DIR> .astropy\r\n2019/12/28 19:01 4,807 .bash_history\r\n2019/09/26 18:19 <DIR> .conda\r\n2019/09/26 18:19 151 .condarc\r\n2019/10/07 10:18 <DIR> .config\r\n2019/11/02 11:50 1,126 .dbshell\r\n2019/07/31 16:49 181 .gitconfig\r\n2019/07/22 20:31 <DIR> .ipython\r\n2019/09/23 16:15 <DIR> .keras\r\n2019/11/06 21:47 <DIR> .matplotlib\r\n2019/08/01 09:36 37 .minttyrc\r\n2019/10/06 20:53 <DIR> .mitmproxy\r\n2019/10/01 15:20 0 .mongorc.js\r\n2019/08/30 15:19 <DIR> .oracle_jre_usage\r\n2019/07/21 23:57 <DIR> .PyCharm2019.1\r\n2019/12/10 17:04 25 .python_history\r\n2019/07/31 16:04 <DIR> .rdm\r\n2019/07/31 16:38 35 .rediscli_history\r\n2019/07/22 20:31 <DIR> .spyder-py3\r\n2019/09/17 17:51 5,339 .viminfo\r\n2019/12/12 13:21 <DIR> 3D Objects\r\n2019/12/12 13:21 <DIR> Contacts\r\n2019/12/31 13:41 <DIR> Desktop\r\n2019/12/18 15:47 <DIR> Documents\r\n2019/12/30 16:34 <DIR> Downloads\r\n2019/12/12 13:21 <DIR> Favorites\r\n2019/10/15 16:36 <DIR> Funshion\r\n2019/12/12 13:21 <DIR> Links\r\n2019/12/12 13:21 <DIR> Music\r\n2019/07/21 23:58 <DIR> OneDrive\r\n2019/12/12 13:21 <DIR> Pictures\r\n2019/12/12 13:21 <DIR> Saved Games\r\n2019/12/12 13:21 <DIR> Searches\r\n2019/12/31 10:27 <DIR> test22\r\n2019/12/12 13:21 <DIR> Videos\r\n 9 個(gè)文件 11,701 字節(jié)\r\n 31 個(gè)目錄 51,681,050,624 可用字節(jié)\r\n'
>>> type(ret)
<class 'str'>
>>>
三:subprocess的Popen方法
并不是所有的操作系統(tǒng)命令都像‘dir’或者‘ipconfig’那樣單純地返回執(zhí)行結(jié)果,還有很多像‘python’這種交互式的命令,你要輸入點(diǎn)什么,然后它返回執(zhí)行的結(jié)果。subprocess中的Popen方法,可以執(zhí)行一些交互性的命令。run方法也可以進(jìn)行一些輸入,不過(guò)很不方便,也不是以代碼的形式驅(qū)動(dòng)的,想要了解的同學(xué)可以看下文末大佬的原文。
Popen的用法和參數(shù)與run()方法基本類(lèi)同,但是它的返回值是一個(gè)Popen對(duì)象,而不是CompletedProcess對(duì)象。
>>> r = subprocess.Popen("dir", shell=True)>>> type(r)
<class 'subprocess.Popen'>
>>> r
<subprocess.Popen object at 0x000001921134EC48>
>>>
要‘python’命令功能,可以按下面的例子操作:
import subprocess
s = subprocess.Popen("python", stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
s.stdin.write(b"import os\n")
s.stdin.write(b"print(os.environ)")
s.stdin.close()
out = s.stdout.read().decode("GBK")
s.stdout.close()
print(out)
另外,也可以把需要執(zhí)行的后續(xù)命令卸載一個(gè)txt文件里,打開(kāi)這個(gè)文件并賦值給stdin這個(gè)參數(shù):
f = open("111.txt", "r+")
s = subprocess.Popen("python",stdout=subprocess.PIPE, stdin=f, shell=True)
out = s.stdout.read().decode("utf-8")
s.stdout.close()
print(out)
111.txt文件中的內(nèi)容是:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-594918.html
import os
print(os.getcwd())
注意:每行代碼后面要加換行。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-594918.html
到了這里,關(guān)于python利用subprocess執(zhí)行交互命令的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!