I have a piece of code that is initializing a logger as below.
logger = logging.getLogger()
hdlr = logging.FileHandler('logfile.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.DEBUG)
Unfortunately this code is being called multiple times, is there any way I can check to see if the handler already exists - I'd prefer to implement this without having to use a Singleton.
EDIT: Sorry, forgot to mention this is on python 2.5 - cheers, Richard
Well the logger.addHandler() will not add a handler if the handler already exists. To check if the handler is already there you can check the logger.handlers list:
Beside that I will suggest putting this code in your main() function if you have one or in the
__init__.py
file of your package so to not have to call it each time. I will also suggest that you use a named logger, and do not use the root logger. Something like this:Hope this was helpful :)
You can also just check to see whether the handler list is empty. Here's the solution I wound up with:
I was seeing the handler added multiple times, so each log message was getting written to the log file more than once, and this fixed it.
As @offbyone comments, it is possible to add redundant handlers to the same instance of the logger. The python docs for logging say-
So we don't need to worry about making the implementation a singleton, as it already is.
Unfortunately the same is not true for the handlers associated with the same instance of the logger. There can be duplicate handlers attached.
Example-
Copy this code and save it in main.py
and the following code in sub.py
Run sub.py
Hence multiple calls to the method returning the same logger added duplicate handlers.
Now, for your question-
Yes, there is-
logger.handlers
returns a list of all the handlers associated with the givenlogger
.Before adding handlers to an instance of the logger, make sure not to add duplicate handlers In main.py, just un-comment the line that says
if not len(logger.handlers):
and indent the following two lines properly-Now again run sub.py
Further, if you want to limit the type of handlers to be added to the logger instance, you can do something like this-
Hope this helps!
Edit:
It turns out that that above statement is not entirely true.
Let's suppose we have created and configured a logger called 'main_logger' in the main module (which simply configures the logger, doesn't return anything).
Now in a sub-module, if we create a child logger following the naming hierarchy 'main_logger.sub_module_logger', we don't need to configure it in the sub-module. Just creation of the logger following the naming hierarchy is sufficient.
And it won't add duplicate handler as well.
Reference- Using logging in multiple modules
If you are familiar with AWS Lambda, then you might already know that in some contexts, the handlers come pre-configured [1]. Assuming
logger.handlers
is not empty, is not enough. I recommend setting an attribute on the logger instance, like so:[1] Using python Logging with AWS Lambda
Try checking if
logger
is already set. For example, if this code is inside a function: