Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python logging issues from multiple modules

I have 3 python modules.

LogManager.py
Runner.py
Other.py

Runner.py is the first main module in the chain of events, and from that module functions inside Other.py are called.

So, inside Runner.py I have a function call to the LogManager.py

logger = LogManager.get_log()

and from there, I can make simple logs, e.g. logger.critical("OHNOES")

What I WANT the get_log function to do, is something similar to a singleton pattern, where if the logger has not been set up, it will set up the logger and return it. Else, it will just return the logger.

Contents of LogManager.py:

import logging

def get_log():
    logger = logging.getLogger('PyPro')
    logger.setLevel(logging.DEBUG)

    # create file handler which logs even debug messages
    fh = logging.FileHandler('pypro.log')
    fh.setLevel(logging.DEBUG)

    # create console handler with a higher log level
    ch = logging.StreamHandler()
    ch.setLevel(logging.WARNING)

    # create formatter and add it to the handlers
    fhFormatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    chFormatter = logging.Formatter('%(levelname)s - %(filename)s - Line: %(lineno)d - %(message)s')
    fh.setFormatter(fhFormatter)
    ch.setFormatter(chFormatter)

    # add the handlers to logger
    logger.addHandler(ch)
    logger.addHandler(fh)

    logger.info("-----------------------------------")
    logger.info("Log system successfully initialised")
    logger.info("-----------------------------------")

    return logger

As you can see, LogManager.get_log() will attempt to set up a log each time it is called. Really, I am a bit confused as to exactly what is happening...

Runner.py calls the get_log function in it's main method. Other.py calls the get_log in the global scope (right after imports, not in any function)

The result is that all of the logs I make are logged twice, as handlers are made twice for the logger.

What is the simplest way that I am missing to make the get_log function to return an instance of the same log elsewise?

like image 978
Colton Phillips Avatar asked Sep 07 '11 23:09

Colton Phillips


People also ask

Is Python logging multiprocessing safe?

As Matino correctly explained: logging in a multiprocessing setup is not safe, as multiple processes (who do not know anything about the other ones existing) are writing into the same file, potentially intervening with each other.

Is logging a singleton Python?

Singleton Logging ServiceLogging service that is guaranteed to be a singleton. Based on Python logging, but every instantiation of LoggingService from any of an application's modules returns the same logger instance.

Is logging in Python thread-safe?

The logging module is thread-safe; it handles the locking for you.


1 Answers

The logging module already implements a singleton pattern for you - when you call logger.getLogger(name), it will create the logger if it hasn't done so already and return it. Although it's not exactly what you're asking for, I would suggest just renaming get_log() to setup_log(), since that's what it does. Then you can just call setup_log() once, at the beginning of your code. Afterwards, when you actually need the logger, just use logging.getLogger() and it will return the already-configured logger.

like image 112
David Z Avatar answered Sep 18 '22 19:09

David Z