Как реализовать ведение журнала с поддержкой многопроцессорной обработки в 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)
Этот пользовательский обработчик журналов позволяет модулям в рамках платформы использовать стандартные методы ведения журнала без необходимости самостоятельно поддерживать многопроцессорную обработку. Сообщения журнала отправляются от дочерних процессов родительскому процессу через канал, гарантируя, что они не будут искажены и правильно записаны в файл журнала.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3