So implementieren Sie Multiprocessing-fähige Protokollierung in Python
Multiprocessing in Python ermöglicht die Erstellung mehrerer Prozesse, die unabhängig voneinander ausgeführt werden. Der Zugriff auf gemeinsam genutzte Ressourcen wie Protokolldateien kann jedoch komplex werden, da möglicherweise mehrere Prozesse gleichzeitig versuchen, auf sie zu schreiben.
Um dieses Problem zu vermeiden, bietet das Python-Multiprocessing-Modul Multiprocessing-fähige Protokollierungsfunktionen auf Modulebene. Dies ermöglicht es dem Logger, eine Verstümmelung von Protokollnachrichten zu verhindern, indem er sicherstellt, dass jeweils nur ein Prozess in einen bestimmten Dateideskriptor schreibt.
Vorhandene Module innerhalb des Frameworks sind jedoch möglicherweise nicht für die Mehrfachverarbeitung geeignet, was zu diesem Bedarf führt für alternative Lösungen. Ein Ansatz besteht darin, einen benutzerdefinierten Protokollhandler zu erstellen, der Protokollierungsnachrichten über eine Pipe an den übergeordneten Prozess sendet.
Eine Implementierung dieses Ansatzes wird unten bereitgestellt:
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)
Dieser benutzerdefinierte Protokollhandler ermöglicht es Modulen innerhalb des Frameworks, Standardprotokollierungspraktiken zu verwenden, ohne selbst Multiprocessing-bewusst sein zu müssen. Die Protokollnachrichten werden von den untergeordneten Prozessen über eine Pipe an den übergeordneten Prozess gesendet, um sicherzustellen, dass sie nicht verstümmelt und korrekt in die Protokolldatei geschrieben werden.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3