Skip to main content
  1. Posts/

Duplicate Logging Messages in Python

··265 words·2 mins·
Python Logging
Table of Contents

When I am working on a project, I find that the same 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.addHandler(stream_handler)
        # 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()
root_logger.addHandler(stream_handler)

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 messages 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: 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 printed only once.

References
#

Related

Make Python logging Work in GCP
·570 words·3 mins
Python Logging GCP
Configure Python logging with dictConfig
··503 words·3 mins
Python Logging
Why Are Some Logging Messages Missing in Python?
··487 words·3 mins
Python Logging