0

Lets say we have such a structure of project:

-main.py

-dir_1/module_log.py

where module_log.py is set o helpers to avoid redundant code in project.

Content of the module_log.py is as follows:

import logging as log

def get_module_logger(module_name):
   logger = log.getLogger(module_name)
   logger.setLevel(log.INFO)

   formatter = log.Formatter('%(asctime)s:%(name)s:%(levelname)s:%(message)s')

   file_handler = log.FileHandler('path/to/logfile/logs.log')
   file_handler.setFormatter(formatter)

   stream_handler = log.StreamHandler()
   stream_handler.setFormatter(formatter)

   logger.addHandler(file_handler)
   logger.addHandler(stream_handler)

   return logger

 def log_info_1():
    logger = get_module_logger(__name__)
    logger.info('\n____________INFO_1____________')

 def log_info_2():
    logger = get_module_logger(__name__)
    logger.info('\n____________INFO_2____________')

And content of the main.py is like:

import module_log as ml

ml.log_info_1()
logger = ml.get_module_logger(__name__)
logger.info('Main log')
ml.log_info_2()

The problem is that the logger logs properly first and second message into file, but the third one is written twice.

Could anyone explain my why is it so? How to avoid such issues?

1 Answer 1

1

Short version

The reason for that is because you register to the same logger the same file \ stream handler more than once.

Long version

In your dir_1/module_log.py module, you define two functions log_info_1 and log_info_2. Each of these functions in turn calls the get_module_logger function with the same module name (in your case __name__ = "dir_1.module_log" )

The get_module_logger registers to the same logger (with that name) two handlers with a formatter.

That logger name is defined "globally" across the python interpreter running your program. so in case you want to get that definition of logger with name <name> you can just call logging.getLogger(<name>) from anywhere in your code and use it freely.

To correct your code, you need to assign handlers to that logger once and then you can use it anywhere.

def get_module_logger(module_name):

   logger = log.getLogger(module_name)
   logger.setLevel(log.INFO)

   if not len(logger.handlers):
       formatter = log.Formatter('%(asctime)s:%(name)s:%(levelname)s:%(message)s')

       file_handler = log.FileHandler('path/to/logfile/logs.log')
       file_handler.setFormatter(formatter)

       stream_handler = log.StreamHandler()
       stream_handler.setFormatter(formatter)

       logger.addHandler(file_handler)
       logger.addHandler(stream_handler)

   return logger
Sign up to request clarification or add additional context in comments.

1 Comment

You're right. Thanks a lot. I suspected that two instances were created, but I didn't know which condition was needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.