如何在 Python 中实现多处理感知日志记录:基于队列的解决方案?

Susan Sarandon
发布: 2024-10-30 12:14:02
原创
571 人浏览过

  How to Implement Multiprocessing-Aware Logging in Python: A Queue-Based Solution?

如何在 Python 中实现多处理感知日志记录

Python 中的多处理允许创建独立运行的多个进程。但是,访问日志文件等共享资源可能会变得复杂,因为多个进程可能会尝试同时写入它们。

为了避免此问题,Python 多处理模块提供了模块级多处理感知日志记录功能。这使得记录器能够通过确保一次只有一个进程写入特定文件描述符来防止日志消息出现乱码。

但是,框架内的现有模块可能不支持多处理,从而导致需要寻求替代解决方案。一种方法涉及创建一个自定义日志处理程序,通过管道将日志消息发送到父进程。

下面提供了此方法的实现:

from logging.handlers import RotatingFileHandler
import multiprocessing, threading, logging, sys, traceback

class MultiProcessingLog(logging.Handler):
    def __init__(self, name, mode, maxsize, rotate):
        logging.Handler.__init__(self)

        # Set up the file handler for the parent process
        self._handler = RotatingFileHandler(name, mode, maxsize, rotate)
        
        # Create a queue to receive log messages from child processes
        self.queue = multiprocessing.Queue(-1)
        
        # Start a thread in the parent process to receive and log messages
        t = threading.Thread(target=self.receive)
        t.daemon = True
        t.start()

    def receive(self):
        while True:
            try:
                # Get a log record from the queue
                record = self.queue.get()
                
                # Log the record using the parent process's file handler
                self._handler.emit(record)
            # Exit the thread if an exception is raised
            except (KeyboardInterrupt, SystemExit):
                raise
            except EOFError:
                break
            except:
                traceback.print_exc(file=sys.stderr)

    def send(self, s):
        # Put the log record into the queue for the receiving thread
        self.queue.put_nowait(s)

    def _format_record(self, record):
        # Stringify any objects in the record to ensure that they can be sent over the pipe
        if record.args:
            record.msg = record.msg % record.args
            record.args = None
        if record.exc_info:
            dummy = self.format(record)
            record.exc_info = None
            
        return record

    def emit(self, record):
        try:
            # Format and send the log record through the pipe
            s = self._format_record(record)
            self.send(s)
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)

    def close(self):
        # Close the file handler and the handler itself
        self._handler.close()
        logging.Handler.close(self)
登录后复制

此自定义日志处理程序允许模块在框架内使用标准日志记录实践,而无需本身具有多处理意识。日志消息通过管道从子进程发送到父进程,确保日志消息不乱码并正确写入日志文件。

以上是如何在 Python 中实现多处理感知日志记录:基于队列的解决方案?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!