简体   繁体   中英

Does Python's logging.config.dictConfig() apply the logger's configuration settings?

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 . 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 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 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.

Ah, I figured out what was wrong. Turns out it was the JSON. From this example 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"
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM