# Code to implement asynchronous logging from a background thread # # Copyright (C) 2016-2019 Kevin O'Connor # # This file may be distributed under the terms of the GNU GPLv3 license. import logging import logging.handlers import queue import threading import time # Class to forward all messages through a queue to a background thread class QueueHandler(logging.Handler): def __init__(self, queue): logging.Handler.__init__(self) self.queue = queue def emit(self, record): try: self.format(record) record.msg = record.message record.args = None record.exc_info = None self.queue.put_nowait(record) except Exception: self.handleError(record) # Class to poll a queue in a background thread and log each message class QueueListener(logging.StreamHandler): def __init__(self): super().__init__() self.bg_queue = queue.Queue() self.bg_thread = threading.Thread(target=self._bg_thread) self.bg_thread.start() def _bg_thread(self): while True: record = self.bg_queue.get(True) if record is None: break self.handle(record) def stop(self): self.bg_queue.put_nowait(None) self.bg_thread.join() MainQueueHandler = None def setup_bg_logging(debuglevel): global MainQueueHandler ql = QueueListener() MainQueueHandler = QueueHandler(ql.bg_queue) root = logging.getLogger() root.addHandler(MainQueueHandler) root.setLevel(debuglevel) return ql def clear_bg_logging(): global MainQueueHandler if MainQueueHandler is not None: root = logging.getLogger() root.removeHandler(MainQueueHandler) root.setLevel(logging.WARNING) MainQueueHandler = None