业务中,python代码需要调用C++程序,获取C++程序执行结果。使用了python的subprocess模块的call调用C++程序。
由于C++程序存在问题,在subprocess.call()中,程序一直没返回,那么python程序就会卡在这里。现在想做以下处理:
(1)如果C++程序调用成功,就直接返回;
(2)如果C++程序卡住,就等待,如果在特定的时间内还没有返回,就杀掉C++程序。
先上代码:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys
import subprocess
import time
from threading import Thread
def GetOcrResult(filepath, return_state):
#str_cmd = "export LD_LIBRARY_PATH=/data/sync360/OcrProcess/bin/:$LD_LIBRARY_PAT && convert %s %s.jpg && cd /data/sync360/OcrProcess/bin && /data/sync360/OcrProcess/bin/OcrReg %s.jpg %s.out" % (filepath, filepath, filepath, filepath)
convert_str_cmd = "convert %s %s.jpg" %(filepath, filepath)
subprocess.call(convert_str_cmd, shell=True)
str_cmd = "/data/sync360/OcrProcess/bin/OcrReg %s.jpg %s.out" % (filepath, filepath)
new_process = subprocess.Popen(str_cmd, shell=True, cwd="/data/sync360/OcrProcess/bin", env={'LD_LIBRARY_PATH':'/data/sync360/OcrProcess/bin/:$LD_LIBRARY_PAT'})
pid = new_process.pid
return_state['pid'] = pid
#print pid
response = new_process.wait()
if response != None:
return_state['response'] = response
def MainFun(filepath):
return_state = {}
t = Thread(target=GetOcrResult, args=(filepath, return_state, ))
#t.setDaemon(True)
t.start()
t.join(15)
if 'response' in return_state:
return return_state['response']
else:
pid = return_state['pid']
str_cmd = "kill %s" %(pid)
subprocess.call(str_cmd, shell=True)
return -1
if __name__ == '__main__':
#path = '/data/sync360/OcrProcess/bin/1'
path = '/data/sync360/OcrProcess/bin/UPLOAD_cmq7xfPP9FQHnzG1c8y07gacVyNOmHZ9'
state = MainFun(path)
print state
# vim: set expandtab sw=4 ts=4 sts=4:
(1)首先看在MainFun函数中,我们创建了一个线程,让这个线程去调用C++模块。其中 t.join(15)是其中的关键:它要求主线程等待子线程的时间,如果子线程在等待的时间没有完成,主线程就不在等待,继续执行下面的代码。参考http://www.cnblogs.com/vingi/articles/2657790.html。
(2)通过上面的设置,主线程就不会被子线程卡住。但我们需要把卡住的子线程杀死,由于子线程中通过subprocess启动了进程,所以需要得到进程的pid:pid = new_process.pid。然后通过一个词典的数据结构告诉主线程。subprocess中的参数参考http://blog.chinaunix.net/uid-26990529-id-3390814.html
(3)在主线程中,通过检查词典的结构,来判断C++进程摸是否被卡住:如果被卡住了,就通过pid杀死。