Marco
Marco

Reputation: 363

Python: How to properly configure logging for a library with dictConfig?

I have a project folder with this structure:

.
├── myapp.py
└── mypackage
    ├── __init__.py
    └── mymodule.py

Now I wanted to configure logging for mypackage as described in the documentation (Configuring Logging for a Library) so I added a NullHandler to the top-level logger in my __init__.py:

import logging
logging.getLogger(__name__).addHandler(logging.NullHandler())

In mymodule.py I then generate an instance of the logger and use it:

import logging
logger=logging.getLogger(__name__)

def myfunc():
    logger.warning('logging from mymodule.py')

In myapp.py I configure the logger like so:

import logging
import logging.config
import mypackage.mymodule as mm

if __name__ == '__main__':

    LOGGING = {'version': 1}
    console_handler = {'class': 'logging.StreamHandler'}
    LOGGING['handlers'] = {'console_handler': console_handler}
    root_logger = {'handlers': ['console_handler']}
    LOGGING['loggers'] = {'': root_logger}
    
    logging.config.dictConfig(LOGGING)
    
    applogger = logging.getLogger(__name__)
    applogger.warning('logging from myapp.py')
    
    mm.myfunc()

Since I am adding handlers to the root-logger ('') I now expected to see both messages (the one in myapp.py and the one in myfunc) but I only see:

$ python -m myapp
logging from myapp.py

What am I doing wrong?

Upvotes: 3

Views: 1067

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1125248

You missed that the logging.config.dictConfig() method disables existing loggers, unless you tell it not to. See the Dict Schema Details section:

disable_existing_loggers - whether any existing non-root loggers are to be disabled. This setting mirrors the parameter of the same name in fileConfig(). If absent, this parameter defaults to True. This value is ignored if incremental is True.

(bold emphasis mine).

Your library loggers were disabled:

(Pdb) logging.getLogger("mypackage.mymodule").disabled
False
(Pdb) n
> /.../myapp.py(16)<module>()
-> applogger = logging.getLogger(__name__)
(Pdb) logging.getLogger("mypackage.mymodule").disabled
True

Either explicitly set it to False, or set incremental to True, e.g.:

    LOGGING = {'version': 1, 'disable_existing_loggers': False}

Upvotes: 2

Related Questions