首頁  >  文章  >  後端開發  >  如何在 Python 中實現多處理感知日誌記錄:基於佇列的解決方案?

如何在 Python 中實現多處理感知日誌記錄:基於佇列的解決方案?

Susan Sarandon
Susan Sarandon原創
2024-10-30 12:14:02559瀏覽

  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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn