Python logging levels are behaving inconsistently
Question: I can't understand why the following code does not produce my debug message
even though effective level is appropriate (output is just `10`)

    
    
    import logging
    
    l = logging.getLogger()
    l.setLevel(logging.DEBUG)
    l.debug("Debug Mess!")
    l.error(l.getEffectiveLevel())
    

while when I add this line after the import: `logging.debug("Start...")`

    
    
    import logging
    
    logging.debug("Start...")
    l = logging.getLogger()
    l.setLevel(logging.DEBUG)
    l.debug("Debug Mess!")
    l.error(l.getEffectiveLevel())
    

it produces following output:

    
    
    DEBUG:root:Debug Mess!
    ERROR:root:10
    

so even though "Start..." is not shown, it starts to log. Why?

It's on Python 3.5. Thanks


Answer: The top-level `logging.debug(..)` call calls the [`logging.basicConfig()`
function](https://docs.python.org/2/library/logging.html#logging.basicConfig)
for you if no handlers have been configured yet on the root logger.

Because using a call to `logging.getLogger().debug()` does _not_ trigger that
call, you don't see any output because there are no handlers to show the
output on.

The Python 3 version of `logger` does have a [`logging.lastResort`
handler](https://docs.python.org/3/library/logging.html#logging.lastResort),
used for when no logging configuration exists, but this handler is configured
to only show messages of level `WARNING` and up, which is why you see your
`ERROR` level message (`10`) printed to STDERR, but not your `DEBUG` level
message. In Python 2 you would get the message _No handlers could be found for
logger "root"_ printed instead, just once for the first attempt to log
anything. I'd not rely on the `lastResort` handler however; instead properly
configure your logging hierarchy with a decent handler configured for your own
needs.

Either call `logging.basicConfig()` yourself, or manually add a handler on the
root logger:

    
    
    l = logging.getLogger()
    l.addHandler(logging.StreamHandler())
    

The above basically does the same thing as a `logging.basicConfig()` call with
no further arguments. The `StreamHandler()` created this way logs to STDERR
and does not further filter on the message level. Note that a
`logging.basicConfig()` call can also set the logging level for you.

