Search code examples
pythonloggingerror-logging

Python Logging - How to inherit root logger level & handler


I am a python newbie, trying to implement logging into my code. I have two modules

main.py submodule.py

main.py

import logging
from logging.handlers import RotatingFileHandler
import submodule


import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

fh = RotatingFileHandler('master.log', maxBytes=2000000, backupCount=10)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)

logger.debug('DEBUG LEVEL - MAIN MODULE')
logger.info('INFO LEVEL - MAIN MODULE')

submodule.loggerCall()

submodule.py

import logging
from logging.handlers import RotatingFileHandler


def loggerCall():
    logger = logging.getLogger(__name__)
#    logger.setLevel(logging.DEBUG)

    fh = RotatingFileHandler('master.log', maxBytes=2000000, backupCount=10)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    logger.addHandler(fh)

    logger.debug('SUBMODULE: DEBUG LOGGING MODE : ')
    logger.info('Submodule: INFO LOG')

    return

I thought as longs as I call the getLogger from my submodule, it should inherit the log level & handler details from root logger. However, in my case, I have to specify log level and handler again in submodule to get them print to same log file.

Also, If I have lots of methods, and classes inside my submodule. How can I go about it without having to define my log level & handler again.

Idea is to have a single log file with main, and sub modules printing in the same log based on the log level set in the main module.


Solution

  • The problem here is that you're not initializing the root logger; you're initializing the logger for your main module.

    Try this for main.py:

    import logging
    from logging.handlers import RotatingFileHandler
    import submodule
    
    logger = logging.getLogger()  # Gets the root logger
    logger.setLevel(logging.DEBUG)
    
    fh = RotatingFileHandler('master.log', maxBytes=2000000, backupCount=10)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    
    logger.debug('DEBUG LEVEL - MAIN MODULE')
    logger.info('INFO LEVEL - MAIN MODULE')
    
    submodule.loggerCall()
    

    Then try this for submodule.py:

    def loggerCall():
        logger = logging.getLogger(__name__)
        logger.debug('SUBMODULE: DEBUG LOGGING MODE : ')
        logger.info('Submodule: INFO LOG')
        return
    

    Since you said you wanted to send log messages from all your submodules to the same place, you should initialize the root logger and then simply use the message logging methods (along with setlevel() calls, as appropriate). Because there's no explicit handler for your submodule, logging.getLogger(__name__) will traverse the tree to the root, where it will find the handler you established in main.py.