Monday, January 19, 2009

[Python]执行一个进程并监视是否超时

用到popen2 module当中的Popen3这个类。用法很简单,创建子进程并立即返回父进程。然后可以用poll()函数检查子进程是否已经结束(未结束的话返回值-1)。
import popen2
def _popen(cmd, timeout = 10, num_retry = 3, logfile = sys.stdout):
    i = 0
    is_timeout = False
    while i <= num_retry:
        print "%dth try"%i, cmd
        sys.stdout.flush()
        i += 1
        t0 = time()
        P = popen2.Popen3(cmd, True)
        prompt = False
        while time() < t0 + timeout and P.poll() == -1:
            sleep(0.1)
        sts = P.poll()
        if sts == -1:
            logfile.write(color_str("command [%s] timeout\n"%(cmd), fg_red))
            if i < num_retry:
                logfile.write(color_str("terminate and try again\n", fg_red))
            logfile.flush()
            is_timeout = True
            os.kill(P.pid, signal.SIGTERM)
        elif sts != 0:
            for l in P.childerr.readlines():
                logfile.write(l)
            if i < num_retry:
                logfile.write(color_str("try again\n", fg_red))
            logfile.flush()
            is_timeout = False
        else:
            is_timeout = False
            break
    logfile.write(color_str("return "+str(sts)+"\n", fg_red))
    sys.stdout.flush()
    if is_timeout:
        return (sts, open("/dev/null", "r"))
    else:
        return (sts, P.fromchild)

按说popen2这个module应该已经deprecated,被subprocess module所取代。不过subprocess.Popen的poll()函数似乎有bug,总是返回None。所以只好还用“古老”的module。

No comments: