Python中判斷subprocess調(diào)起的shell命令是否結(jié)束
前言
最近在使用subprocess遇到個(gè)問(wèn)題,折騰了好半天才找到簡(jiǎn)單的解決辦法,在這里記錄下。
環(huán)境
Python:2.7.10
庫(kù):subprocess, logging
問(wèn)題
使用subprocess的Popen類(lèi)來(lái)執(zhí)行shell命令,要怎么樣才能知道命令執(zhí)行結(jié)束了,以此來(lái)執(zhí)行回調(diào)方法。
解決辦法
使用subprocess.Popen.poll方法來(lái)獲取命令的執(zhí)行情況。
poll方法的返回值有兩種情況
1. 當(dāng)命令未運(yùn)行結(jié)束的時(shí)候,返回None
2. 當(dāng)命令結(jié)束時(shí),返回命令的返回值
演示
這里使用logging模塊來(lái)輔助顯示命令執(zhí)行時(shí)間

分別使用兩種調(diào)用shell命令的方式來(lái)測(cè)試
shell=True

shell=False

完整演示

補(bǔ)充:system函數(shù)返回(如何判斷調(diào)用的shell命令是否執(zhí)行成功)
例:
status = system("./test.sh");
1、先統(tǒng)一兩個(gè)說(shuō)法:
(1)system返回值:指調(diào)用system函數(shù)后的返回值,比如上例中status為system返回值
(2)shell返回值:指system所調(diào)用的shell命令的返回值,比如上例中,test.sh中返回的值為shell返回值。
2、如何正確判斷test.sh是否正確執(zhí)行?
僅判斷status是否==0?或者僅判斷status是否!=-1?
都錯(cuò)!
3、man中對(duì)于system的說(shuō)明
RETURN VALUE
The value returned is -1 on error (e.g. fork() failed), and the return
status of the command otherwise. This latter return status is in the
format specified in wait(2). Thus, the exit code of the command will
be WEXITSTATUS(status). In case /bin/sh could not be executed, the
exit status will be that of a command that does exit(127).
看得很暈吧?
system函數(shù)對(duì)返回值的處理,涉及3個(gè)階段:
階段1:創(chuàng)建子進(jìn)程等準(zhǔn)備工作。如果失敗,返回-1。
階段2:調(diào)用/bin/sh拉起shell腳本,如果拉起失敗或者shell未正常執(zhí)行結(jié)束(參見(jiàn)備注1),原因值被寫(xiě)入到status的低8~15比特位中。system的man中只說(shuō)明了會(huì)寫(xiě)了127這個(gè)值,但實(shí)測(cè)發(fā)現(xiàn)還會(huì)寫(xiě)126等值。
階段3:如果shell腳本正常執(zhí)行結(jié)束,將shell返回值填到status的低8~15比特位中。
備注1:
只要能夠調(diào)用到/bin/sh,并且執(zhí)行shell過(guò)程中沒(méi)有被其他信號(hào)異常中斷,都算正常結(jié)束。
比如:不管shell腳本中返回什么原因值,是0還是非0,都算正常執(zhí)行結(jié)束。即使shell腳本不存在或沒(méi)有執(zhí)行權(quán)限,也都算正常執(zhí)行結(jié)束。
如果shell腳本執(zhí)行過(guò)程中被強(qiáng)制kill掉等情況則算異常結(jié)束。
如何判斷階段2中,shell腳本是否正常執(zhí)行結(jié)束呢?系統(tǒng)提供了宏:WIFEXITED(status)。如果WIFEXITED(status)為真,則說(shuō)明正常結(jié)束。
如何取得階段3中的shell返回值?你可以直接通過(guò)右移8bit來(lái)實(shí)現(xiàn),但安全的做法是使用系統(tǒng)提供的宏:WEXITSTATUS(status)。
由于我們一般在shell腳本中會(huì)通過(guò)返回值判斷本腳本是否正常執(zhí)行,如果成功返回0,失敗返回正數(shù)。
所以綜上,判斷一個(gè)system函數(shù)調(diào)用shell腳本是否正常結(jié)束的方法應(yīng)該是如下3個(gè)條件同時(shí)成立:
(1)-1 != status
(2)WIFEXITED(status)為真
(3)0 == WEXITSTATUS(status)
注意:
根據(jù)以上分析,當(dāng)shell腳本不存在、沒(méi)有執(zhí)行權(quán)限等場(chǎng)景下時(shí),以上前2個(gè)條件仍會(huì)成立,此時(shí)WEXITSTATUS(status)為127,126等數(shù)值。
所以,我們?cè)趕hell腳本中不能將127,126等數(shù)值定義為返回值,否則無(wú)法區(qū)分中是shell的返回值,還是調(diào)用shell腳本異常的原因值。shell腳本中的返回值最好多1開(kāi)始遞增。
判斷shell腳本正常執(zhí)行結(jié)束的健全代碼如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t status;
status = system("./test.sh");
if(status == -1)
{
printf("system error... \n");
}
else
{
if(WIFEXITED(status))
{
if(0 == WEXITSTATUS(status))
{
printf("run successfully... \n");
}
else
{
printf("run failed %d \n",WEXITSTATUS(status));
}
}
else
{
printf("exit code %d \n",WEXITSTATUS(status));
}
}
return 0;
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
Python實(shí)現(xiàn)簡(jiǎn)單的四則運(yùn)算計(jì)算器
相信大家在學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)時(shí),就學(xué)習(xí)了簡(jiǎn)單四則運(yùn)算表達(dá)式求解的一個(gè)算法,可惜一直沒(méi)有自己動(dòng)手實(shí)現(xiàn)過(guò)這個(gè)算法。最近重拾數(shù)據(jù)結(jié)構(gòu)與算法,恰巧又正在用Python比較頻繁,所幸就用它來(lái)實(shí)現(xiàn)這個(gè)算法,雖然網(wǎng)上有很多代碼,不過(guò)作為一個(gè)學(xué)習(xí)者,還是應(yīng)當(dāng)親自動(dòng)手實(shí)現(xiàn)。2016-11-11
python3使用print打印帶顏色的字符串代碼實(shí)例
這篇文章主要介紹了python3使用print打印帶顏色的字符串代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
Python使用FastAPI制作一個(gè)視頻流媒體平臺(tái)
在構(gòu)建視頻流媒體平臺(tái)時(shí),用戶(hù)認(rèn)證與視頻上傳是兩個(gè)至關(guān)重要的功能,FastAPI作為一個(gè)高效的Web框架,可以輕松處理這些需求,下面我們看看具體實(shí)現(xiàn)方法吧2025-04-04
使用 Python 列出串口的實(shí)現(xiàn)方法
有時(shí)在編程時(shí),我們需要獲取有關(guān)系統(tǒng)中可用通信端口的信息, 我們將討論如何使用 Python 來(lái)做到這一點(diǎn),將討論使用串口或 com 端口的通信, 我們將深入探索 Python 包,以幫助我們獲得系統(tǒng)的可用通信端口,感興趣的朋友一起看看吧2023-08-08
基于Python實(shí)現(xiàn)一個(gè)AI物體識(shí)別
計(jì)算機(jī)視覺(jué)是其中的一大領(lǐng)域?,應(yīng)用場(chǎng)景也比較多,這篇文章主要為大家詳細(xì)介紹了如何基于Python實(shí)現(xiàn)一個(gè)AI物體識(shí)別功能,需要的小伙伴可以了解下2024-11-11
python并發(fā)編程多進(jìn)程之守護(hù)進(jìn)程原理解析
這篇文章主要介紹了python并發(fā)編程多進(jìn)程之守護(hù)進(jìn)程原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08

