I have the following code in a file called 'logger.py'
import logging
format = '%(asctime)s - %(name)-30s - %(levelname)-8s - %(message)s'
logging.basicConfig(level=logging.DEBUG,
format=format)
formatter = logging.Formatter(format)
fh = logging.FileHandler('test.log')
fh.setFormatter(formatter)
fh.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setFormatter(formatter)
ch.setLevel(logging.INFO)
logging.getLogger().addHandler(fh)
logging.getLogger().addHandler(ch)
and in another file
import logging
import logger
logger = logging.getLogger(__name__)
logger.info('Staring Scheduler')
and I am getting the following console output
2014-07-14 22:27:10,915 - __main__ - INFO - Staring Scheduler
2014-07-14 22:27:10,915 - __main__ - INFO - Staring Scheduler
I am unable to disable the double output. I would like to use the extra streamhandler to customize the log level printed to the console. In the future I would also like to use the RotatingFileHandler instead of the simple file handler.
Does anybody know how to achieve this while keeping the simple logger setup as in the second file? I have search, but no solution seems to do it.
UPDATE 1 (Solved)
File logger.py
import logging
logging.getLogger().setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)-30s - %(levelname)-8s - %(message)s')
fh = logging.FileHandler('test.log')
fh.setFormatter(formatter)
fh.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setFormatter(formatter)
ch.setLevel(logging.ERROR)
logging.getLogger().addHandler(fh)
logging.getLogger().addHandler(ch)
File test.py
import logging
import logger
logger = logging.getLogger(__name__)
logger.debug('Debug message')
logger.info('Info message')
logger.warning('Warning message')
logger.error('Error message')
logger.critical('Critical message')
Console output:
2014-07-15 09:47:58,171 - __main__ - ERROR - Error message
2014-07-15 09:47:58,171 - __main__ - CRITICAL - Critical message
Test.log
content:
2014-07-15 09:47:58,171 - __main__ - DEBUG - Debug message
2014-07-15 09:47:58,171 - __main__ - INFO - Info message
2014-07-15 09:47:58,171 - __main__ - WARNING - Warning message
2014-07-15 09:47:58,171 - __main__ - ERROR - Error message
2014-07-15 09:47:58,171 - __main__ - CRITICAL - Critical message
The root of the hierarchy of loggers is called the root logger. That's the logger used by the functions debug() , info() , warning() , error() and critical() , which just call the same-named method of the root logger. The functions and the methods have the same signatures.
The root logger resides at the top of the logger hierarchy. It is exceptional in three ways: it always exists, its level cannot be set to null. it cannot be retrieved by name.
One of the advantages of using the logging module to track our codes is the ability to format the messages based on our needs. For example, in my code, I would like to log the date and time with appropriate messages. Here is an example. And here is the output.
The reason you are seeing the double output is because you have set up two StreamHandlers in your first file; logger.py
One explicitly in this line:
ch = logging.StreamHandler()
the other in this line:
logging.basicConfig(level=logging.DEBUG,
According to the docs for logging.basicConfig:
Does basic configuration for the logging system by creating a StreamHandler with a default Formatter and adding it to the root logger.
So you should remove the basicConfig line.
However after you remove it you will need to set the level for the root logger to DEBUG, since you do this in the basicConfig line:
logging.getLogger().setLevel(logging.DEBUG)
You're calling logging.basicConfig()
, which defaults to a StreamHandler
. Instead, you should set the level manually.
>>> import logging
>>> format = '%(asctime)s - %(name)-30s - %(levelname)-8s - %(message)s'
>>> formatter = logging.Formatter(format)
>>> fh = logging.FileHandler('test.log')
>>> fh.setFormatter(formatter)
>>> fh.setLevel(logging.DEBUG)
>>> ch = logging.StreamHandler()
>>> ch.setFormatter(formatter)
>>> ch.setLevel(logging.INFO)
>>> logging.getLogger().addHandler(fh)
>>> logging.getLogger().addHandler(ch)
>>> l = logging.getLogger(__name__)
>>> l.setLevel(logging.INFO)
>>> l.info("HI")
2014-07-15 08:46:50,000 - __main__ - INFO - HI
The file contents are:
msvalkon@lunkwill:~$ cat test.log
2014-07-15 08:46:50,000 - __main__ - INFO - HI
Also, you're overwriting your logger
. In your another file
:
import logging
import logger # <-- importing logger.py
logger = logging.getLogger(__name__) # <-- overwriting the logger name, nothing from logger.py is now availabe
logger.info('Staring Scheduler') # This is just a logging object
Your logging configuration is done in this case, because the import will go through your code. In some other cases might not be true. Fix by changing the variable name or change the configuration scheme entirely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With