sankalpjonn / timeloop

An elegant periodic task executor
MIT License
245 stars 49 forks source link

Multiple messages sent, need to remove the logging handlers. #24

Open coolkau opened 2 years ago

coolkau commented 2 years ago

Every time timeloop is started it adds a new logging handlers causing issues e.g. when using flask. Messages are sent multiple times. This could be fixed by releasing the handlers in the stop method by adding:

        for h in self.logger.handlers:
            self.logger.removeHandler(h)

Example:

tl = Timeloop()
tl = Timeloop()
tl = Timeloop()
tl = Timeloop()
tl = Timeloop()

every message is sent 5 times:


[2022-11-07 15:00:12,195] [timeloop] [INFO] Starting Timeloop..
[2022-11-07 15:00:12,195] [timeloop] [INFO] Starting Timeloop..
[2022-11-07 15:00:12,195] [timeloop] [INFO] Starting Timeloop..
[2022-11-07 15:00:12,195] [timeloop] [INFO] Starting Timeloop..
[2022-11-07 15:00:12,195] [timeloop] [INFO] Starting Timeloop..
[2022-11-07 15:00:12,195] [timeloop] [INFO] Starting Timeloop..

Note that in this example the timeloop will still print multiple messages after my fix, as only the handler of the last instance is removed. I guess to make it cleanly the timeloop should be a "with as", the logging handler should only be attached once the process is started, use of the destructor... or check for existing handlers before creating a new one.

coolkau commented 2 years ago

Disclaimer: I am not an expert so my suggestion might be wrong but this fixed it for me:

Move the logger out of __init__ into a separate function and call those functions in start() and stop():

    def add_logger(self):
        logger = logging.getLogger('timeloop')
        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.INFO)
        formatter = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
        ch.setFormatter(formatter)
        logger.addHandler(ch)
        logger.setLevel(logging.INFO)
        self.logger = logger

    def remove_logger(self):
        for h in self.logger.handlers:
            self.logger.removeHandler(h)