Colton Phillips
Colton Phillips

Reputation: 373

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?

Upvotes: 12

Views: 14479

Answers (1)

David Z
David Z

Reputation: 131670

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.

Upvotes: 17

Related Questions