No handlers could be found for logger
I am newbie to python. I was trying logging in python and I came across No handlers could be found for logger error while trying to print some warning through logger instance. Below is the code I tried
import logging
logger=logging.getLogger('logger')
logger.warning('The system may break down')
And I get this error No handlers could be found for logger "logger"
What's confusing me is when I first try to print warning using logging
and then through logger
, it works fine, like
>>> import logging
>>> logging.warning('This is a WARNING!!!!')
WARNING:root:This is a WARNING!!!!
>>>
>>> logger.warning('WARNING!!!!')
WARNING:logger:WARNING!!!!
Can someone throw some light on what's happening in second scenario?
Call logging.basicConfig():
>>> import logging
>>> logging.basicConfig()
>>> logger = logging.getLogger('logger')
>>> logger.warning('The system may break down')
WARNING:logger:The system may break down
For logging some message through logger
, in Python at least one handler should be added to the logger
object. By default the debug
, warn
and other functions in logging
module will call basicConfig
which in turn will add a StreamHandler
to the root logger
.
It's always recommended to add your required Handler to your logger object you are writing for your module.
You could refer to official Python docs, which has an awesome tutorial or you can better check out the source code of logging module yourself.
Simply you can check the source in Python shell itself by,
import logging
import inspect
print(inspect.getsource(logging))
Finally, calling the basicConfig
explicitly will resolve the issue.
import logging
logging.basicConfig()
logger = logging.getLogger('logger')
logger.warning('The system may break down')
Additional to phd's answer, calling logging.basicConfig()
is a convenient function which will get you a default StreamHandler
and a Formatter
. That is enough if you want to quickly have a logging functionality. You can customize it's behaviour by passing basicConfig
some arguments:
Add Useful parameters: output timestamp alongside the message
logger = logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
This should be fine for most of the one off needs. If you need more control about your config, you can add more sophisticated behaviours by defining the logger's attributes your self.
Sophisticated Example: without using the
basicConfig
function
import logging
logger = logging.getLogger("mylogger")
streamHandler = logging.StreamHandler()
streamHandler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)
logger.info("Files copied")
logger.warning("disk quota exceeded")
>> 2017-12-06 11:11:12, 090 - mylogger - INFO Files copied
>> 2017-12-06 11:11:12, 091 - mylogger - WARNING disk quota exceeded
The next step in a bigger environment, would be deriving a new logger from the previously created one, to first keep the formatting and as well to maintain a "log hierarchy"
logger2 = logging.getLogger("mylogger.new")
logger2.info("New Logger info")
>> 2017-12-06 11:11:12, 091 - mylogger.new - New logger info
A good reference is the logging cookbook: https://docs.python.org/2/howto/logging-cookbook.html