- 實(shí)際應(yīng)用場(chǎng)景:某應(yīng)用使用Python實(shí)現(xiàn)了某算法,其中Python會(huì)調(diào)用一個(gè)
demo.exe。根據(jù)不同的輸入數(shù)據(jù),demo.exe運(yùn)行時(shí)間有長有短,短的10s內(nèi),長的10+分鐘
問題:
- Python算法是由后臺(tái)API(Java)調(diào)用的,有實(shí)時(shí)性要求(比如1分鐘內(nèi)出結(jié)果)
-
demo.exe運(yùn)行時(shí)特別耗資源(CPU和內(nèi)存),因此同時(shí)運(yùn)行的demo.exe不能太多,否則導(dǎo)致電腦卡死
思路:
想辦法設(shè)置一個(gè)超時(shí)時(shí)間,如果超時(shí)時(shí)間內(nèi)能夠分析完畢,返回分析結(jié)果;如果timeout了,殺死demo.exe進(jìn)程,返回一個(gè)默認(rèn)的結(jié)果。
嘗試過的解決辦法 - 多線程
多線程中使用os.system()運(yùn)行demo.exe,線程設(shè)置守護(hù)線程為True,入口函數(shù)threadTest()啟動(dòng)新線程后,time.sleep(10)一個(gè)固定時(shí)間,比如10s,然后判斷保存結(jié)果的隊(duì)列threadQueue中有沒有數(shù)據(jù),如果沒有數(shù)據(jù),使用os.system('taskkill /F /IM demo.exe')殺死進(jìn)程
def run_demo_exe():
...
def threadTest():
# 線程
openposeThread = threading.Thread(target=run_demo_exe)
openposeThread.setDaemon(True)
openposeThread.start()
time.sleep(10)
if threadQueue.empty():
os.system('taskkill /F /IM demo.exe')
return RESULT_DIC['NO_PERSON']
else:
return threadQueue.get()
問題
os.system('taskkill /F /IM demo.exe')會(huì)殺死所有名字是demo.exe的進(jìn)程,也就是其它任務(wù)的進(jìn)程也會(huì)被殺死
嘗試過的解決辦法 - 多進(jìn)程
思路跟使用多線程的思路一樣,只不過想通過kill子進(jìn)程實(shí)現(xiàn)kill任務(wù)對(duì)應(yīng)的demo.exe進(jìn)程,而不影響其它任務(wù)的demo.exe進(jìn)程
def threadTest():
# 進(jìn)程
p = multiprocessing.Process(target=run_demo_exe)
p.daemon = True
p.start()
time.sleep(10)
if threadQueue.empty():
p.terminate()
return RESULT_DIC['NO_PERSON']
else:
return threadQueue.get()
問題
實(shí)測(cè)后發(fā)現(xiàn),kill子進(jìn)程后,當(dāng)前任務(wù)對(duì)應(yīng)的demo.exe進(jìn)程會(huì)繼續(xù)運(yùn)行下去
最終的解決辦法 - subprocess.Popen
使用subprocess.Popen取代os.system()運(yùn)行demo.exe,subprocess.Popen會(huì)返回一個(gè)對(duì)象,該對(duì)象可以設(shè)置超時(shí)時(shí)間,timeout之后可以調(diào)用該對(duì)象的kill()直接殺死當(dāng)前任務(wù)對(duì)應(yīng)的demo.exe進(jìn)程,而不影響其它任務(wù)的進(jìn)程
def run_demo_exe():
myPopenObj = subprocess.Popen("D:/demo/OpenPoseDemo.exe")
try:
myPopenObj.wait(timeout=SECONDS_TIMEOUT)
except Exception as e:
print("===== process timeout ======")
myPopenObj.kill()
return None
...