Question

I created a module named log.py where a function defines how the log will be registered. Here is the atomic code:

import logging
import time

def set_up_log():
    """
    Create a logging file.
    """ 
    #
    # Create the parent logger.
    #
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    #
    # Create a file as handler.
    #
    file_handler = logging.FileHandler('report\\activity.log')
    file_handler.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(filename)s - %(name)s - %  (levelname)4s - %(message)s')
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)
    #
    # Start recording.
    #
    logger.info('______ STARTS RECORDING _______')

if __name__=='__main__':
    set_up_log()

A second module named read_file.py is using this log.py to record potential error.

import logging
import log
log.set_up_log()
logger = logging.getLogger(__name__)


def read_bb_file(input_file):
    """
    Input_file must be the path.
    Open the source_name and read the content. Return the result.
    """
    content = list()
    logger.info('noi')
    try:
        file = open(input_file, 'r')
    except IOError, e:
        logger.error(e)
    else:
        for line in file:
            str = line.rstrip('\n\r')
            content.append(str)
        file.close()
        return content

if __name__ == "__main__":
    logger.info("begin execution")
    c = read_bb_file('textatraiter.out')
    logger.info("end execution")

In the command prompt lauching read_file.py, I get this error:

No handlers could be found for logger "__main__"

My result in the file is the following

2014-05-12 13:32:58,690 - log.py - log - INFO - ______ STARTS RECORDING _______

I read lots of topics here and on Py Doc but it seems I did not understand them properly since I have this error. I add I would like to keep the log settlement appart in a function and not define it explicitely in my main method.

Was it helpful?

Solution

You have 2 distinct loggers and you're only configuring one.

The first is the one you make in log.py and set up correctly. Its name however will be log, because you have imported this module from read_file.py. The second logger, the one you're hoping is the same as the first, is the one you assign to the variable logger in read_file.py. Its name will be __main__ because you're calling this module from the command line. You're not configuring this logger.

What you could do is to add a parameter to set_up_log to pass the name of the logger in, e.g.

def set_up_log(logname):

    logger = logging.getLogger(logname)

That way, you will set the handlers and formatters for the correct logging instance.

Organizing your logs in a hierarchy is the way logging was intended to be used by Vinay Sajip, the original author of the module. So your modules would only log to a logging instance with the fully qualified name, as given by __name__. Then your application code could set up the loggers, which is what you're trying to accomplish with your set_up_log function. You just need to remember to pass it the relevant name, that's all. I found this reference very useful at the time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top