Python日志从多个进程重定向stdout

3 投票
1 回答
2404 浏览
提问于 2025-04-16 07:56

我正在尝试捕获多个进程的标准错误输出(stderr)和标准输出(stdout),并使用Python的日志模块将它们的输出写入一个日志文件。下面的代码似乎可以做到这一点。目前,我是通过轮询每个进程的标准输出,如果有数据就写入日志。有没有更好的方法来实现这个?

另外,我还想要一个所有个别进程活动的主日志,也就是说,我希望能够自动(不需要轮询)将每个进程的标准输出和标准错误输出写入一个主日志。这可能吗?

谢谢

class MyProcess:
def __init__(self, process_name , param):
    self.param = param
    self.logfile = logs_dir + "Display_" + str(param) + ".log"
    self.args = [process_name, str(param)]
    self.logger_name = process_name + str(param)
    self.start()
    self.logger = self.initLogger()

def start(self):
    self.process = Popen(self.args, bufsize=1, stdout=PIPE, stderr=STDOUT) #line buffered
    # make each processes stdout non-blocking
    fd = self.process.stdout
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)

def initLogger(self):
    f  = logging.Formatter("%(levelname)s -%(name)s - %(asctime)s - %(message)s")
    fh = logging.handlers.RotatingFileHandler(self.logfile, maxBytes=max_log_file_size, backupCount = 10)
    fh.setFormatter(f)

    logger = logging.getLogger(self.logger_name)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(fh) #file handler
    return logger

def getOutput(self): #non blocking read of stdout
    try:
        return self.process.stdout.readline()
    except:
        pass

def writeLog(self):
    line = self.getOutput()
    if line:
        self.logger.debug(line.strip()) 
        #print line.strip()



process_name = 'my_prog'
num_processes = 10
processes=[]

for param in range(num_processes)
    processes.append(MyProcess(process_name,param))

while(1):
    for p in processes:
        p.writeLog()

    sleep(0.001)

1 个回答

1

这里有几个选择:

  • 非阻塞I/O: 这就是你已经做的事情 :)

  • select模块 你可以使用 poll()select() 来处理不同输入的读取。

  • 线程: 为你想要监控的每个文件描述符创建一个线程,并使用阻塞I/O。虽然不建议在处理大量文件描述符时使用,但至少在Windows上可以工作。

  • 第三方库: 显然,你还可以使用 Twistedpyevent 来进行异步文件访问,不过我自己从来没有这样做过...

想了解更多信息,可以看看这个关于Python非阻塞I/O的视频

既然你的方法似乎有效,如果处理器负载对你来说没什么影响,那就继续用这个方法吧。如果负载让你觉得不舒服,那我建议在Unix上使用 select.select()

至于你问的主日志记录器:因为你想要分开记录各个输出,所以不能把所有内容都重定向到一个主日志记录器。你需要手动处理这个。

撰写回答