When I am working on a project, I find that the logging message is printed twice. The following minimal code can reproduce this issue:

Source code for logger.py:

import sys
import logging

class MyLogger:
def __init__(self, name):
self.logger = logging.getLogger(name)
self.logger.setLevel(logging.DEBUG)

stream_handler = logging.StreamHandler(sys.stderr)
formatter = logging.Formatter(
"[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s", "%Y-%m-%d %H:%M:%S"
)
stream_handler.setFormatter(formatter)

stream_handler.setLevel(logging.DEBUG)
# self.logger.propagate = False

def info(self, message):
self.logger.info("{}".format(message))

my_logger = MyLogger("Logging debug")


Source code for main.py:

import logging

from logger import my_logger

root_logger = logging.getLogger()
stream_handler = logging.StreamHandler()

my_logger.info("demo")
my_logger.info("another test")


When we run main.py, we can see that each log message is printed twice on the console:

[2020-06-19 21:56:53] [Logging debug] [INFO] demo
demo
[2020-06-19 21:56:53] [Logging debug] [INFO] another test
another test


But why? The reason is that, when we use logging.getLogger() without any argument, we will get the root logger. my_logger in logger.py is thus a child logger of this root logger. By default, child logger message will be propagated to the logger in the upper hierarchy.

We have two options: (1) Disable propagation from child logger (2) Do not use root logger.

Option 1: in the logger.py, uncomment the line self.logger.propagate = False to make sure that child logger does not propagate its message to the root logger.

Option 2: We simply do not use root logger in main.py. For example, we can get another logger by using another_logger = logging.getLogger('main'). In this way, logging message from my_logger have no relationship with another_logger. So the logging messages are print only once.