Duplicate log output when using Python logging module
The logging.getLogger()
is returns the same instance for a given name. (Documentation)
The problem is that every time you call myLogger()
, it's adding another handler to the instance, which causes the duplicate logs.
Perhaps something like this?
import os
import time
import datetime
import logging
loggers = {}
def myLogger(name):
global loggers
if loggers.get(name):
return loggers.get(name)
else:
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
now = datetime.datetime.now()
handler = logging.FileHandler(
'/root/credentials/Logs/ProvisioningPython'
+ now.strftime("%Y-%m-%d")
+ '.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
loggers[name] = logger
return logger
Python Logging Duplicate Output
As far as I remember the setting propagates to higher level (ancestor) loggers. You can read about it here.
I would suggest adding logger.propagate = False
after initializing logger a
:
logger = logging.getLogger('a')
logger.propagate = False
logger.setLevel(logging.DEBUG)
duplicate output in simple python logging configuration
I figured this out, thanks Paco for pointing me in the right direction
it turns out that when getLogger
is called, handlers are added to it:
>>> print(effectivehandlers(logger))
[<logging.StreamHandler object at 0x305ad90>, <logging.FileHandler object at 0x305ae10>]
>>> logging.getLogger(name) #the same logger
<logging.Logger object at 0x7fa08fb9b2d0>
>>> print(effectivehandlers(logger))
[<logging.StreamHandler object at 0x305ad90>, <logging.FileHandler object at 0x305ae10>, <logging.StreamHandler object at 0x305ad90>, <logging.FileHandler object at 0x305ae10>]
Now, both the child and the parent have the same handlers. Hence duplicate outputs.
Python logging duplicated
Every time fetch_logger
is called it adds a new FileHandler
to the logger. Each FileHandler
writes to the log file, resulting in the repeating output in the file.
One solution is to call the logger's hasHandlers method. This will return True if any handlers have been configured on the logger, and then you can delete them.
def fetchLogger(name="None") :
logger = logging.getLogger(__name__)
if logger.hasHandlers():
# Logger is already configured, remove all handlers
logger.handlers = []
# Configure the logger as before.
...
Duplicate log output, but no duplicate handlers
Loggers propagate log events to their ancestors' handlers by default. a_logger
may only have one handler, but its parent, the root logger, also has a handler (actually the same handler). a_logger.info('hi')
is handled by both handlers (actually the same handler twice).
You don't need to attach the same handler to every logger. Attaching it to the root logger is enough.
log messages appearing twice with Python Logging
You are calling configure_logging
twice (maybe in the __init__
method of Boy
) : getLogger
will return the same object, but addHandler
does not check if a similar handler has already been added to the logger.
Try tracing calls to that method and eliminating one of these. Or set up a flag logging_initialized
initialized to False
in the __init__
method of Boy
and change configure_logging
to do nothing if logging_initialized
is True
, and to set it to True
after you've initialized the logger.
If your program creates several Boy
instances, you'll have to change the way you do things with a global configure_logging
function adding the handlers, and the Boy.configure_logging
method only initializing the self.logger
attribute.
Another way of solving this is by checking the handlers attribute of your logger:
logger = logging.getLogger('my_logger')
if not logger.handlers:
# create the handlers and call logger.addHandler(logging_handler)
Logging module for print statements: Duplicate log entries
Here's at least a partial answer to your first question. You're getting those blank lines on eachprint
becauseprint
statements in Python 2.x potentially callstdout.write()
twice, once with the data from evaluating the expression in the statement, and then again if the optional newline hasn't been suppressed by a trailing comma.
Also, if anINFO
level message is sent to a logger set at alevel
of'NOTSET'
, the message will also be echoed on sys.stderr
by default according to the logger documentation -- which is why you see the console output even when the Tee
is in effect. There are no duplicate log entries that I can see.
To prevent the blanks lines, try using thisTee
class definition. Note thewrite()
method modifications (updated to be a singleton to match your "EDIT SECTION (3)"):
class Tee(object):
_instance = None
def __init__(self, logger):
self.stdout = sys.stdout
self.logger = logger
sys.stdout = self
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Tee, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __del__(self):
sys.stdout = self.stdout
def write(self, data):
data = data.rstrip('\r\n')
if data: # anything left?
self.logger.info(data)
With this and all your other updates in place it seems to work for me (including with the uncommented aux2
stuff. Are there some remaining problems from your point of view? If so, your initially long question has gotten even more so and should be completely cleaned-up leaving just the most recent code and focus on any remaining issue(s).
Reset python Logger to prevent duplicate logging records
Solved it:
I created a new method destroy_logger
which is triggered at the end of the entire process. It closes and deletes all handlers. This is what's inside of the method:
def destroy_logger():
global logger
while logger.hasHandlers():
logger.handlers[0].close
logger.removeHandler(logger.handlers[0])
This question here helped me solving it. It also mentions a problem I noticed as well: The log file cannot be deleted as long as the IDE is opened. This problem is also solved by my method above.
Related Topics
Python's JSON Module, Converts Int Dictionary Keys to Strings
Difference Between Returns and Printing in Python
Shuffle an Array with Python, Randomize Array Item Order with Python
Convert Row to Column Header for Pandas Dataframe,
Why Don't Methods Have Reference Equality
If Range() Is a Generator in Python 3.3, Why How to Not Call Next() on a Range
Executing Multiple Statements with Postgresql via SQLalchemy Does Not Persist Changes
Python Dictionary:Typeerror: Unhashable Type: 'List'
Getting the Caller Function Name Inside Another Function in Python
Take the Content of a List and Append It to Another List
Numpy - Create Matrix with Rows of Vector
Standard Way to Embed Version into Python Package
Why Are Str.Count('') and Len(Str) Giving Different Output
Importerror: No Module Named Matplotlib.Pyplot
How to Qcut with Non Unique Bin Edges
Nested Dictionary to Multiindex Dataframe Where Dictionary Keys Are Column Labels