Skip to main content
 首页 » 编程设计

Python 日志记录从多个进程重定向标准输出

2025年05月04日6飞鱼

我正在 try catch 多个进程的标准错误和标准输出,并使用 Python 日志记录模块将它们的输出写入日志文件。下面的代码似乎可以实现这一点。目前我轮询每个进程 stdout 并在有任何数据时写入记录器。有没有更好的方法。

此外,我还希望拥有所有单个进程事件的主日志,换句话说,我想自动(无需轮询)将每个进程的所有标准输出/标准错误写入主记录器。这可能吗?

谢谢

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) 

请您参考如下方法:

你的选择是

  • 非阻塞 I/O:这就是您所做的 :)

  • select module : 您可以使用 poll() 或 select() 为不同的输入分派(dispatch)读取。

  • 线程:为您要监视的每个文件描述符创建一个线程并使用阻塞 I/O。不建议使用大量文件描述符,但至少它适用于 Windows。

  • 第三方库:显然,你也可以使用Twisted或 pyevent用于异步文件访问,但我从来没有这样做过...

有关更多信息,请观看此 video on non-blocking I/O with Python

既然你的方法似乎有效,我会坚持下去,如果强加的处理器负载不会打扰你的话。如果是这样,我会在 Unix 上使用 select.select()。

至于你关于主记录器的问题:因为你想开球单独的输出,你不能将所有内容重定向到主记录器。您必须手动执行此操作。