Jordan
Jordan

Reputation: 70

Python Logging with dictConfig - "No handlers could be found"

I am trying to setup logging on multiple modules using logging.config.dictConfig. I can see logging from __main__, but can't see any output from my modules. I feel like I'm missing something extremely basic.

Here is the directory structure:

settings.json
main.py
a/
`---b.py
`---__init__.py

Here are the contents of settings.json

{
    "version": 1,
    "disable_existing_loggers": false,
    "formatters": {
        "simple": {
            "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        }
    },

    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "level": "INFO",
            "formatter": "simple",
            "stream": "ext://sys.stdout"
        }
    },

    "loggers": {
        "a.b": {
            "level": "ERROR",
            "handlers": ["console"],
            "propagate": "no"
        }
    },

    "root": {
        "level": "INFO",
        "handlers": ["console"]
    }
}

Here is main.py

import logging
import logging.config
import json

from a import b

if __name__ == "__main__":
    logger = logging.getLogger(__name__)
    with open("settings.json", "r") as log_settings:
        log_config = json.loads(log_settings.read())
        logging.config.dictConfig(log_config)
    logger.info("Hello from main!")

And, finally, here are the contents of b.py

import logging

print "Name of module: {0}".format(__name__)
logger = logging.getLogger(__name__)
logger.warning("Test warning!")

When running this, I get the following output:

Name of module: a.b
No handlers could be found for logger "a.b"
2015-10-13 18:26:12,138 - __main__ - INFO - Hello from main!

Why is there no handler found for a.b? I specify it in settings.json?

Upvotes: 3

Views: 2753

Answers (1)

Vinay Sajip
Vinay Sajip

Reputation: 99385

It's because your code in b.py gets executed before your call to dictConfig() - it's executed at the line from a import b. If you move the stuff in b.py into a function foo() and call b.foo() from main after calling dictConfig(), you shouldn't see the No handlers message. You still won't see the "Test warning!" message, of course, since you've set the level to ERROR for that logger.

Also note that you have duplicated the console handler for root and a.b loggers, so you will see messages logged in a.b twice in the output. This is because you have set "propagate" to "no", which Python evaluates as True. To avoid propagation, set it to false in the JSON (no quotes) which will become False in Python.

Upvotes: 3

Related Questions