- 实际应用场景:某应用使用Python实现了某算法,其中Python会调用一个
demo.exe
。根据不同的输入数据,demo.exe
运行时间有长有短,短的10s内,长的10+分钟
问题:
- Python算法是由后台API(Java)调用的,有实时性要求(比如1分钟内出结果)
-
demo.exe
运行时特别耗资源(CPU和内存),因此同时运行的demo.exe
不能太多,否则导致电脑卡死
思路:
想办法设置一个超时时间,如果超时时间内能够分析完毕,返回分析结果;如果timeout了,杀死demo.exe
进程,返回一个默认的结果。
尝试过的解决办法 - 多线程
多线程中使用os.system()
运行demo.exe,线程设置守护线程为True,入口函数threadTest()
启动新线程后,time.sleep(10)
一个固定时间,比如10s,然后判断保存结果的队列threadQueue
中有没有数据,如果没有数据,使用os.system('taskkill /F /IM demo.exe')
杀死进程
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')
会杀死所有名字是demo.exe
的进程,也就是其它任务的进程也会被杀死
尝试过的解决办法 - 多进程
思路跟使用多线程的思路一样,只不过想通过kill子进程实现kill任务对应的demo.exe
进程,而不影响其它任务的demo.exe
进程
def threadTest():
# 进程
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()
问题
实测后发现,kill子进程后,当前任务对应的demo.exe
进程会继续运行下去
最终的解决办法 - subprocess.Popen
使用subprocess.Popen
取代os.system()
运行demo.exe
,subprocess.Popen
会返回一个对象,该对象可以设置超时时间,timeout之后可以调用该对象的kill()
直接杀死当前任务对应的demo.exe
进程,而不影响其它任务的进程
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
...