python popen.stdout.read阻塞 解决办法

需求:利用python的subprocess模块结合logging模块实现监控子程序运行情况

代码如下(程序阻塞在stdout.readz这里,日志里找不到hang on...................):

import os
import sys
import time
import subprocess
import logging
from logging.handlers import RotatingFileHandler

todaylog = time.strftime('%Y-%m-%d', time.localtime(time.time())).decode('utf-8')
LOG_PATH_FILE = "C:\my.log"
LOG_MODE = 'a'
LOG_MAX_SIZE = 10 * 1024 * 1024  # 10M per file
LOG_MAX_FILES = 10  # 10 Files: my.1, my.2, ...
LOG_LEVEL = logging.DEBUG

LOG_FORMAT = "%(asctime)s %(levelname)-10s[%(filename)s:%(lineno)d(%(funcName)s)] %(message)s"

handler = RotatingFileHandler(LOG_PATH_FILE, LOG_MODE, LOG_MAX_SIZE, LOG_MAX_FILES)
formatter = logging.Formatter(LOG_FORMAT)
handler.setFormatter(formatter)

Logger = logging.getLogger()
Logger.setLevel(LOG_LEVEL)
Logger.addHandler(handler)

pid = os.getpid()


def print_error(s):
    print '\033[31m[%d: ERROR] %s\033[31;m' % (pid, s)


def print_info(s):
    print '\033[32m[%d: INFO] %s\033[32;m' % (pid, s)


def print_warning(s):
    print '\033[33m[%d: WARNING] %s\033[33;m' % (pid, s)


def start_child_proc(command):
    try:
        if command is None:
            raise OSError, "Invalid command"
        
        #Logger.info("def start_child_proc(command, merged):")
        child = None
        child = subprocess.Popen(command, stdout=subprocess.PIPE)
        return child
    except subprocess.CalledProcessError:
        pass  # handle errors in the called executable
    except OSError:
        raise OSError, "Failed to run command!"


def run_forever(command):
    #print_info("start child process with command: " + ' '.join(command))
    Logger.info("start child process with command: " + ' '.join(command))

    child = start_child_proc(command)
    failover = 0

    while True:
        while child.poll() != None:
            failover = failover + 1
            #print_warning("child process shutdown with return code: " + str(child.returncode))
            Logger.critical("child process shutdown with return code: " + str(child.returncode))

            Logger.info('------------------------------------------')
            #print_warning("restart child process again, times=%d" % failover)
            Logger.info("restart child process again, times=%d" % failover)
            child = start_child_proc(command)
        # read child process stdout and log it
        ch = child.stdout.read()
        print "hang on..................."
        Logger.info("hang on...................")
        if ch != '':
            chlist = ch.split('\n')
        for chline in chlist:
            Logger.info(chline)

    Logger.exception("!!!should never run to this!!!")


if __name__ == "__main__":
    run_forever(['python', 'test.py'])

为什么有时候能够正常运行,有时候会阻塞?查找资料找到相关解释:

还有Stack Overflow上的解释:

如何解决呢?为了防止这种情况的发生,统一使用out, err = child.communicate()代替read()

猜你喜欢

转载自my.oschina.net/u/3636678/blog/2986091
今日推荐