This is my standard boilerplate code for adding any logging functionality in an app. This makes starting and working on projects super easy. But sometimes if the project involves multiples modules, there is an annoying little thing that the log is printed multiple times on the console.
def create_logger(name="imap", path=os.getcwd()):
fname = os.path.join(path, "{}.log".format(name))
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# Create handlers
c_handler = logging.StreamHandler()
f_handler = logging.FileHandler(fname, mode="w")
c_handler.setLevel(logging.INFO)
f_handler.setLevel(logging.DEBUG)
# Create formatters and add it to handlers
c_format = logging.Formatter("%(levelname)s %(message)s")
f_format = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
c_handler.setFormatter(c_format)
f_handler.setFormatter(f_format)
# Add handlers to the logger
logger.addHandler(c_handler)
logger.addHandler(f_handler)
return logger
def get_logger(name: str):
logger = logging.getLogger(name)
return logger
In one particular project, which was using multiple modules, this setup was causing the logging messages to print multiple times. This duplicate output in a simple python logging configuration was not harmful but was annoying.
After a few googles searches, false re-starts and reading multiple debates on stack overflow found the solution that was as simple as this.
Solution
logger.propagate = False
Full code that works without the flaw is shown below
def create_logger(name="imap", path=os.getcwd()):
fname = os.path.join(path, "{}.log".format(name))
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# Create handlers
c_handler = logging.StreamHandler()
f_handler = logging.FileHandler(fname, mode="w")
c_handler.setLevel(logging.INFO)
f_handler.setLevel(logging.DEBUG)
# Create formatters and add it to handlers
c_format = logging.Formatter("%(levelname)s %(message)s")
f_format = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
c_handler.setFormatter(c_format)
f_handler.setFormatter(f_format)
# Add handlers to the logger
logger.addHandler(c_handler)
logger.addHandler(f_handler)
logger.propagate = False
return logger
def get_logger(name: str):
logger = logging.getLogger(name)
return logger
Other related posts that you may like…