Question: I am currently developing a core utils package where I want to set some logging properties (I know that this is not best practice, but it´s for interal purposes and intended to generate logs). When I now import the package nothing gets logged: # core.__main__.py class BaseLoggerConfig(BaseModel): LOG_FORMAT: str = "%(levelprefix)s %(asctime)s %(name)s:%(lineno)d: %(message)s" DATEFMT: str = "%Y-%m-%d %H:%M:%S" LOG_LEVEL: int = logging.INFO version: int = 1 disable_existing_loggers: bool = False formatters: dict = { "default": { # "()": "uvicorn.logging.DefaultFormatter", "fmt": LOG_FORMAT, "datefmt": DATEFMT, }, } filters: dict = {} handlers: dict = { "default": { "formatter": "default", "class": "logging.StreamHandler", "stream": "ext://sys.stderr", } } loggers: dict = {} def __init__(self, name: str, **data): super().__init__(**data) self.loggers[name] = { "handlers": ["default"], "level": self.LOG_LEVEL, "propagate": False, } LOG_CONFIG = BaseLoggerConfig(__name__) logging.config.dictConfig(LOG_CONFIG)  - core.__main__ Level: INFO Handlers: ['StreamHandler']  I now have logging in my other files, like: # core.utils import logging logger = logging.getLogger(__name__) def test(): logger.info(f"I am a log from {__name__}")  # test.py import logging from core.utils import test logger = logging.getLogger(__name__) test()  What am I missing?

Answer: There are a couple of tweaks that need to be made here. First, the file in which you configure your loggers should not be core/__main__.py, it should be core/__init__.py. __main__.py is used when you want to python -m core, which would run __main__.py. Second, the fmt key in your formatter config should be called format. You can see the official docs for logging.config. Third, in your LOG_FORMAT, levelprefix is not a valid field name. You probably want to use levelname which is "INFO", "DEBUG", etc. Putting it all together: # core/__init__.py import logging import logging.config from pydantic import BaseModel class BaseLoggerConfig(BaseModel): LOG_FORMAT: str = "%(levelname)s %(asctime)s %(name)s:%(lineno)d: %(message)s" DATEFMT: str = "%Y-%m-%d %H:%M:%S" LOG_LEVEL: int = logging.INFO version: int = 1 disable_existing_loggers: bool = False formatters: dict = { "default": { # "()": "uvicorn.logging.DefaultFormatter", "format": LOG_FORMAT, "datefmt": DATEFMT, }, } filters: dict = {} handlers: dict = { "default": { "formatter": "default", "class": "logging.StreamHandler", "stream": "ext://sys.stderr", } } loggers: dict = {} def __init__(self, name: str, **data): super().__init__(**data) self.loggers[name] = { "handlers": ["default"], "level": self.LOG_LEVEL, "propagate": False, } LOG_CONFIG = BaseLoggerConfig(__name__) logging.config.dictConfig(LOG_CONFIG)  # core/utils.py import logging logger = logging.getLogger(__name__) def test(): logger.info(f"I am a log from {__name__}")  # test.py import logging from core.utils import test logger = logging.getLogger(__name__) test()  Output: INFO 2024-11-30 11:06:28 core.utils:8: I am a log from core.utils   EDIT: I realized that your %(levelprefix)s comes from uvicorn's formatter. In that case, you can uncomment your line  # "()": "uvicorn.logging.DefaultFormatter",  and undo changing the key to format. Which means: # core/__init__.py # ... class BaseLoggerConfig(BaseModel): LOG_FORMAT: str = "%(levelprefix)s %(asctime)s %(name)s:%(lineno)d: %(message)s" DATEFMT: str = "%Y-%m-%d %H:%M:%S" # ... formatters: dict = { "default": { # "()": "uvicorn.logging.DefaultFormatter", "format": LOG_FORMAT, "datefmt": DATEFMT, }, } # ...  Output: ("INFO" text is green) INFO: 2024-12-01 14:13:14 core.utils:6: I am a log from core.utils