Search code examples
pythonpython-2.7python-module

Weird stuff happening while importing modules


I hate to give the question this heading but I actually don't know whats happening so here it goes.

I was doing another project in which I wanted to use logging module. The code is distributed among few files & instead of creating separate logger objects for seperate files, I thought of creating a logs.py with contents

import sys, logging

class Logger:
    def __init__(self):
        formatter = logging.Formatter('%(filename)s:%(lineno)s %(levelname)s:%(message)s')
        stdout_handler = logging.StreamHandler(sys.stdout)
        stdout_handler.setFormatter(formatter)
        self.logger=logging.getLogger('')
        self.logger.addHandler(stdout_handler)
        self.logger.setLevel(logging.DEBUG)

    def debug(self, message):
        self.logger.debug(message)

and use this class like (in different files.)

import logs
b = logs.Logger()
b.debug("Hi from a.py")
  1. I stripped down the whole problem to ask the question here. Now, I have 3 files, a.py, b.py & main.py. All 3 files instantiate the logs.Logger class and prints a debug message.
  2. a.py & b.py imports "logs" and prints their debug message.
  3. main.py imports logs, a & b; and prints it own debug message.

The file contents are like this: https://i.sstatic.net/a4ssr.png

Why is debug message from b.py printed 2 times & from main.py 3 times?


Solution

  • Specify a name for the logger, otherwise you always use root logger.

    import sys, logging
    
    class Logger:
        def __init__(self, name):
            formatter = logging.Formatter('%(filename)s:%(lineno)s %(levelname)s:%(message)s')
            stdout_handler = logging.StreamHandler(sys.stdout)
            stdout_handler.setFormatter(formatter)
            self.logger=logging.getLogger(name)
            self.logger.addHandler(stdout_handler)
            self.logger.setLevel(logging.DEBUG)
    
        def debug(self, message):
            self.logger.debug(message)
    

    http://docs.python.org/howto/logging.html#advanced-logging-tutorial :

    A good convention to use when naming loggers is to use a module-level logger, in each module which uses logging, named as follows:

    logger = logging.getLogger(__name__)