"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Comment implémenter la journalisation multitraitement en Python : une solution basée sur une file d'attente ?

Comment implémenter la journalisation multitraitement en Python : une solution basée sur une file d'attente ?

Publié le 2024-11-03
Parcourir:664

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

Comment implémenter la journalisation multitraitement en Python

Le multitraitement en Python permet la création de plusieurs processus qui s'exécutent indépendamment. Cependant, l'accès aux ressources partagées telles que les fichiers journaux peut devenir complexe, car plusieurs processus peuvent tenter d'y écrire simultanément.

Pour éviter ce problème, le module multitraitement Python fournit des fonctionnalités de journalisation prenant en charge le multitraitement au niveau du module. Cela permet à l'enregistreur d'éviter la confusion des messages de journal en garantissant qu'un seul processus écrit dans un descripteur de fichier spécifique à la fois.

Cependant, les modules existants dans le cadre peuvent ne pas prendre en charge le multitraitement, ce qui nécessite pour des solutions alternatives. Une approche consiste à créer un gestionnaire de journaux personnalisé qui envoie des messages de journalisation au processus parent via un canal.

Une implémentation de cette approche est fournie ci-dessous :

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)

Ce gestionnaire de journaux personnalisé permet aux modules du framework d'utiliser des pratiques de journalisation standard sans avoir à être eux-mêmes conscients du multitraitement. Les messages de journal sont envoyés des processus enfants au processus parent via un canal, garantissant qu'ils ne sont pas tronqués et écrits correctement dans le fichier journal.

Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3