Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Logging - Only for own imported modules

Tags:

python

logging

referring to this question here: LINK How can I set up a config, that will only log my root script and my own sub-scripts? The question of the link asked for disabling all imported modules, but that is not my intention.

My root setup:

import logging
from exchangehandler import send_mail
log_wp = logging.getLogger(__name__)

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(levelname)s [%(filename)s]: %(name)s %(funcName)20s - Message: %(message)s',
                    datefmt='%d.%m.%Y %H:%M:%S',
                    filename='C:/log/myapp.log',
                    filemode='a')

handler = logging.StreamHandler()
log_wp.addHandler(handler)

log_wp.debug('This is from root')

send_mail('[email protected]', 'Request', 'Hi there')

My sub-module exchangehandler.py:

import logging
log_wp = logging.getLogger(__name__)

def send_mail(mail_to,mail_subject,mail_body, mail_attachment=None):
log_wp.debug('Hey this is from exchangehandler.py!')
    m.send_and_save()

myapp.log:

16.07.2018 10:27:40 - DEBUG [test_script.py]: __main__                   <module> - Message: This is from root
16.07.2018 10:28:02 - DEBUG [exchangehandler.py]: exchangehandler        send_mail - Message: Hey this is from exchangehandler.py!
16.07.2018 10:28:02 - DEBUG [folders.py]: exchangelib.folders            get_default_folder - Message: Testing default <class 'exchangelib.folders.SentItems'> folder with GetFolder
16.07.2018 10:28:02 - DEBUG [services.py]: exchangelib.services          get_payload - Message: Getting folder ArchiveDeletedItems (archivedeleteditems)
16.07.2018 10:28:02 - DEBUG [services.py]: exchangelib.services          get_payload - Message: Getting folder ArchiveInbox (archiveinbox)

My problem is, that the log-file contains also a lot of information of the exchangelib-module, that is imported in exchangehandler.py. Either the imported exchangelib-module is configured incorrectly or I have made a mistake. So how can I reduce the log-output only to my logging messages?

EDIT: An extract of the folder.py of the exchangelib-module. This is not anything that I have written:

import logging
log = logging.getLogger(__name__)

def get_default_folder(self, folder_cls):
        try:
            # Get the default folder
            log.debug('Testing default %s folder with GetFolder', folder_cls)
            # Use cached instance if available
            for f in self._folders_map.values():
                if isinstance(f, folder_cls) and f.has_distinguished_name:
                    return f
            return folder_cls.get_distinguished(account=self.account)
like image 325
Erik Steiner Avatar asked Jul 16 '18 08:07

Erik Steiner


1 Answers

The imported exchangelib module is not configured at all when it comes to logging. You are configuring it implicitly by calling logging.basicConfig() in your main module.

exchangelib does create loggers and logs to them, but by default these loggers do not have handlers and formatters attached, so they don't do anything visible. What they do, is propagating up to the root logger, which by default also has no handlers and formatters attached.

By calling logging.basicConfig in your main module, you actually attach handlers to the root logger. Your own, desired loggers propagate to the root logger, hence the messages are written to the handlers, but the same is true for the exchangelib loggers from that point onwards.

You have at least two options here. You can explicitly configure "your" named logger(s):

main module

import logging
log_wp = logging.getLogger(__name__) # or pass an explicit name here, e.g. "mylogger"
hdlr = logging.StreamHandler()
fhdlr = logging.FileHandler("myapp.log")
log_wp.addHandler(hdlr)
log_wp.addHandler(fhdlr)
log_wp.setLevel(logging.DEBUG)

The above is very simplified. To explicitly configure multiple named loggers, refer to the logging.config HowTo

If you rather want to stick to just using the root logger (configured via basicConfig()), you can also explicitly disable the undesired loggers after exchangelib has been imported and these loggers have been created:

logging.getLogger("exchangelib.folders").disabled = True
logging.getLogger("exchangelib.services").disabled = True

If you don't know the names of the loggers to disable, logging has a dictionary holding all the known loggers. So you could temporarily do this to see all the loggers your program creates:

# e.g. after the line 'log_wp.addHandler(handler)'
print([k for k in logging.Logger.manager.loggerDict])

Using the dict would also allow you to do sth. like this:

for v in logging.Logger.manager.loggerDict.values():
    if v.name.startswith('exchangelib'):
        v.disabled = True
like image 141
shmee Avatar answered Nov 07 '22 07:11

shmee