Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python logging module is printing lines multiple times

Tags:

python

logging

I have the following code:

import logging class A(object):     def __init__(self):         self._l = self._get_logger()      def _get_logger(self):         loglevel = logging.INFO         l = logging.getLogger(__name__)         l.setLevel(logging.INFO)         h = logging.StreamHandler()         f = logging.Formatter('%(asctime)s %(levelname)s %(message)s')         h.setFormatter(f)         l.addHandler(h)         l.setLevel(loglevel)         return l        def p(self, msg):         self._l.info(msg)  for msg in ["hey", "there"]:     a = A()     a.p(msg) 

The output that I get is:

2013-07-19 17:42:02,657 INFO hey 2013-07-19 17:42:02,657 INFO there 2013-07-19 17:42:02,657 INFO there 

Why is "there" being printed twice? Similarly, if I add another object of class A inside the loop and print a message, it gets printed thrice.

The documentation says that logging.getLogger() will always return the same instance of the logger if the name of the logger matches. In this case, the name does match. Should it not return the same logger instance? If it is infact doing so, why is the message getting printed multiple times?

like image 536
Nikhil Singh Avatar asked Jul 19 '13 12:07

Nikhil Singh


People also ask

Is Python logging a singleton?

Singleton Logging ServiceLogging service that is guaranteed to be a singleton. Based on Python logging, but every instantiation of LoggingService from any of an application's modules returns the same logger instance.

What is the difference between print and logging in Python?

print will just print the text to console. console. log() actually records it and we can use it for many purposes like email it for bug report.


1 Answers

logger is created once, but multiple handlers are created.

Create A once.

a = A() for msg in ["hey", "there"]:     a.p(msg) 

Or change _get_logger as follow:

def _get_logger(self):     loglevel = logging.INFO     l = logging.getLogger(__name__)     if not getattr(l, 'handler_set', None):         l.setLevel(loglevel)         h = logging.StreamHandler()         f = logging.Formatter('%(asctime)s %(levelname)s %(message)s')         h.setFormatter(f)         l.addHandler(h)         l.setLevel(loglevel)         l.handler_set = True     return l   

UPDATE

Since Python 3.2, you can use logging.Logger.hasHandlers to see if this logger has any handlers configured. (thanks @toom)

def _get_logger(self):     loglevel = logging.INFO     l = logging.getLogger(__name__)     if not l.hasHandlers():         ...     return l 
like image 91
falsetru Avatar answered Sep 24 '22 01:09

falsetru