Python 日志记录 - 仅适用于自己导入的模块

Eri*_*ner 5 python logging

在这里参考这个问题:LINK 如何设置一个配置,它只会记录我的根脚本和我自己的子脚本?链接的问题要求禁用所有导入的模块,但这不是我的意图。

我的根设置

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('address@eg.com', 'Request', 'Hi there')
Run Code Online (Sandbox Code Playgroud)

我的子模块 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()
Run Code Online (Sandbox Code Playgroud)

我的应用程序日志

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)
Run Code Online (Sandbox Code Playgroud)

我的问题是,日志文件还包含大量的 exchangelib 模块的信息,这些信息是在 exchangehandler.py 中导入的。导入的 exchangelib-module 配置不正确,或者我犯了一个错误。那么如何才能将日志输出仅减少到我的日志消息呢?

编辑:exchangelib 模块的folder.py 的摘录。这不是我写的任何东西:

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)
Run Code Online (Sandbox Code Playgroud)

shm*_*mee 10

导入的 exchangelib 模块在日志记录方面根本没有配置。您通过调用logging.basicConfig()主模块来隐式配置它。

exchangelib 确实会创建记录器并记录到它们,但默认情况下这些记录器没有附加处理程序和格式化程序,因此它们不做任何可见的事情。他们所做的是传播到根记录器,默认情况下它也没有附加处理程序和格式化程序。

通过调用logging.basicConfig您的主模块,您实际上将处理程序附加到根记录器。您自己想要的记录器传播到根记录器,因此消息被写入处理程序,但从那时起,exchangelib 记录器也是如此。

您在这里至少有两个选择。您可以显式配置“您的”命名记录器:

主模块

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)
Run Code Online (Sandbox Code Playgroud)

上面已经非常简化了。要显式配置多个命名记录器,请参阅logging.config HowTo

如果您只想坚持使用根记录器(通过 配置basicConfig()),您还可以在导入 exchangelib 并创建这些记录器后显式禁用不需要的记录器:

logging.getLogger("exchangelib.folders").disabled = True
logging.getLogger("exchangelib.services").disabled = True
Run Code Online (Sandbox Code Playgroud)

如果您不知道要禁用的记录器的名称,请使用logging包含所有已知记录器的字典。因此,您可以暂时执行此操作以查看您的程序创建的所有记录器:

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

使用 dict 还可以让你做某事。像这样:

for v in logging.Logger.manager.loggerDict.values():
    if v.name.startswith('exchangelib'):
        v.disabled = True
Run Code Online (Sandbox Code Playgroud)