''' @author: devone, 02-2020 ''' import logging.config import os import sys import threading import traceback import yaml from path import Path HERE = Path(__file__).parent LOGDIR = HERE LOGCONF = HERE / 'logging.yml' SYS_EXCEPT_HOOK = sys.excepthook def start(name="main", level=0, filename="", replace=False): # charge la configuration du logging depuis le fichier 'logging.yaml' with open(LOGCONF, 'rt') as f: conf = yaml.load(f, Loader=yaml.FullLoader) if level: conf["loggers"][name]["level"] = level if not filename: filename = LOGDIR / r'{}.log'.format(name) if replace: filename.remove_p() conf["handlers"]["file"]["filename"] = filename logging.config.dictConfig(conf) logger = logging.getLogger(name) def _excepthook(typ, value, trace): """ Remplace la gestion d'erreur standard, pour logger aussi les erreurs non gérées """ logger.error("{}\n{}\n{}".format(typ.__name__, value, ''.join(traceback.format_tb(trace)))) SYS_EXCEPT_HOOK(typ, value, trace) sys.excepthook = _excepthook class LogPipe(threading.Thread): def __init__(self, logger_name, level=logging.INFO): """Setup the object with a logger and a loglevel and start the thread """ threading.Thread.__init__(self) self.logger_name = logger_name self.daemon = False self.level = level self.fdRead, self.fdWrite = os.pipe() self.pipeReader = os.fdopen(self.fdRead) self.start() def fileno(self): """Return the write file descriptor of the pipe """ return self.fdWrite def run(self): """Run the thread, logging everything. """ logger = logging.getLogger(self.logger_name) for line in iter(self.pipeReader.readline, ''): logger.log(self.level, line.strip('\n')) self.pipeReader.close() def close(self): """Close the write end of the pipe. """ os.close(self.fdWrite)