美文网首页我爱编程
BugKiller: Python subprocess超时后,

BugKiller: Python subprocess超时后,

作者: Fr1day | 来源:发表于2016-10-11 17:36 被阅读1781次

    出现问题的代码是酱汁的:

    process = subprocess.Popen("phantomjs crawler.js {url} {method} {data}", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    try:
        (output, error) = process.communicate(timeout=TIMEOUT)
        re_result = re.findall(r"~~~~123(.*?)321~~~~", output.decode(), re.I|re.S)
        if len(re_result) == 0:
            print_error("Can't find result, %s" % cmd)
            return []
    
        res = simplejson.loads(re_result[0])
        for item in res:
            item["url"] = Parser.get_url(url, item["url"])
    
        return res
    except subprocess.TimeoutExpired:
        process.kill()
        print_error("TIMEOUT: %s" % cmd)
    except Exception as e:
        print(e)
    

    由于PhantomJS的问题,导致任务超时。超时关闭是在Python中处理的,调用了process.kill(),但在实际测试中发现PhantomJS进程并没有被kill掉。

    为了Debug,我在process.kill()之前,插入了一句print(process.pid)。原本以为是kill()函数没有正常运行,但让人惊讶的是,根据打印出来的pid,进程中并没有subprocess进程残留,打印的pid和未结束的PhantomJS进程pid并不相同,且phantomjs.pid = process.pid + 1。看起来是subprocess在调度任务的时候,开启了两个进程,在父进程被kill的时候,并没有kill子进程(或者两个进程之间根本没有父子关系)。

    很快查到了问题所在,shell=True 参数会模拟在shell中执行,先是起了shell进程,再从shell起了phantomjs进程。解决方案(
    去掉了shell=True,改用list格式传参。):

    process = subprocess.Popen(["phantomjs", "crawler.js", {url}, {method}, {data}], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    

    相关文章

      网友评论

        本文标题:BugKiller: Python subprocess超时后,

        本文链接:https://www.haomeiwen.com/subject/ajebyttx.html