Does Python's logging.config.dictConfig() apply the logger's configuration settings?
Question: I've been trying to implement a basic logger that writes to a file in Python
3.5, loading the settings from a JSON config file. I'll show my code first;

`log_config.json`

    
    
    {
        "version": 1,
        "disable_existing_loggers": "false",
        "logging": {
            "formatters": {
                "basic": {
                    "class": "logging.Formatter",
                    "style": "%",
                    "datefmt": "%I:%M:%S",
                    "format": "[%(asctime)] %(levelname:<8s): (name:<4s): %(message)"
                }
            },
    
            "handlers": {
                "file": {
                    "class": "logging.handlers.FileHandler",
                    "level": "DEBUG",
                    "formatter": "basic",
                    "filename": "test.log",
                    "mode": "a",
                    "encoding": "utf-8"
                }
            },
    
            "loggers": { },
    
            "root": {
                "handlers": ["file"],
                "level": "DEBUG"
            }
        }
    }
    

And `logger.py`

    
    
    import json
    import logging
    import logging.config
    
    logging.basicConfig()
    with open("log_config.json", "r") as fd:
        logging.config.dictConfig(json.load(fd))
    
    logger = logging.getLogger()  # Returns the "root" logger
    print(logger.getEffectiveLevel())  # Check what level of messages will be shown
    
    logger.debug("Test debug message")
    logger.info("Test info message")
    logger.warn("Test warning message")
    logger.error("Test error message")
    logger.critical("Test critical message")
    

When run with `python3 logger.py` produces the output (in the terminal);

    
    
    30
    WARNING:root:Test warning message
    ERROR:root:Test error message
    CRITICAL:root:Test critical message
    

First; Looking at [ Python's logging
levels](https://docs.python.org/3.5/library/logging.html#logging-levels). 30
is the default logging level of 'WARNING'. This contradicts the setting for
both of the `level` properties I set in the handler and the root logger. It
seems the JSON is incorrect or I have missed a function call to apply it.

Second; [This thread](http://stackoverflow.com/questions/13805905/python-
logging-dictconfig) makes me think that although I load the config with the
call of `dictConfig()`, I still need to apply it to the logging with further
calls in my `logger.py` file. It seems a bit redundant that you have the
config and then have to verbosely apply each setting anyway.

Additionally; When I tried using the [Configuration file
format](https://docs.python.org/3.5/library/logging.config.html#configuration-
file-format) it worked as I thought it would. Namely; loading the file with
one function call and being able to make logging calls straight away. This is
confusing, because why would the older `fileConfig()` call used with this
format offer a more streamlined functionality than `dictConfig()` with JSON or
YAML?

Ultimately, I'm a bit confused and would like to figure this out. I appreciate
your time and help.

EDIT: From Alex.P's comment, I added the following handler to
`log_config.json` and changed the handler the root to it.

    
    
    "console": {
                "class": "logging.StreamHandler",
                "level": "DEBUG",
                "formatter": "basic",
                "stream": "ext://sys.stdout"
            },
    

Checking the output, it is the same as above.


Answer: Ah, I figured out what was wrong. Turns out it was the JSON. From [this
example](https://gist.github.com/glenfant/4358668) which I was basing my work
off of, it has an extra `logging` property in the JSON, which encapsulates all
the loggers, handlers etc.

Removing that property and having the hierarchy more like a YAML file (which I
also tested, and got working correctly), it works as expected. I could even
remove the extra call to `basicConfig` in my `logger.py`.

Final JSON;

    
    
    {
        "version": 1,
        "disable_existing_loggers": "false",
        "formatters": {
            "basic": {
                "class": "logging.Formatter",
                "datefmt": "%I:%M:%S",
                "format": "%(asctime)s %(levelname)s %(name)s %(message)s"
            }
        },
    
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "level": "DEBUG",
                "formatter": "basic",
                "stream": "ext://sys.stdout"
            },
            "file": {
                "class": "logging.FileHandler",
                "level": "DEBUG",
                "formatter": "basic",
                "filename": "test.log",
                "mode": "w",
                "encoding": "utf-8"
            }
        },
    
        "loggers": { },
    
        "root": {
            "handlers": ["console", "file"],
            "level": "DEBUG"
        }
    }
    

