【问题标题】:Python Logging - Only for own imported modulesPython 日志记录 - 仅适用于自己导入的模块
【发布时间】:2018-12-23 18:10:32
【问题描述】:

在这里提到这个问题: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')

我的子模块 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)

我的问题是,日志文件还包含大量的 exchangelib-module 信息,这些信息是在 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)

【问题讨论】:

    标签: python logging


    【解决方案1】:

    在进行日志记录时,根本没有配置导入的 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)
    

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

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

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

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

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

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

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

    【讨论】:

    • 谢谢!我在 main.py 中使用了 fileConfig 来设置控制台的输出,file1 带有级别调试,file2 带有级别信息。但是,我的 main.py 中出现了 ValueError。这不会记录到 file1 或 file2。我只能在鞋底看到它。我怎么能在不知道它可能发生的情况下捕捉到这样的错误? link_to_config
    • ValueError 是否与您的新日志记录设置有关?您能否将 Traceback 添加到您的问题中?
    • 日志设置没问题。我的常规代码中有一个问题会引发 ValueError:Traceback(最近一次调用最后一次):
      x_usr_name, x_password, x_mail, x_servername, x_server, x_endpoint, x_contacts = load_setup()
      ValueError: too many values to解包(预期为 7)
      但这是我的日志记录设置的一个很好的示例,它不会在我的文件中记录此错误。我只是在 PyCharm 的控制台中看到它。所以通常写一个会引发错误的函数,你会看到它没有记录在日志文件中。
    • 在这种情况下,只需将引发错误的代码部分放在try:-except ValueError as e:-block 中。在except 里面你会做某事。喜欢log_wp.exception(e)。请注意,如果捕获的异常的严重性需要这样做,您必须在将捕获的异常记录到 except 块后重新引发它以终止您的程序。
    • 这不是日志记录引入的问题,日志记录本身也无法解决。只有在您指示它这样做时,日志才会起作用。您可以将整个主程序包装在 try-except Exception as e 中。这将捕获在执行期间引发但未被捕获的任何异常。但是,开发人员有责任通过在处理之前验证输入或相应地处理潜在的异常来识别和处理执行期间可能发生的所有潜在错误情况。
    猜你喜欢
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 2020-08-11
    • 2019-12-08
    • 1970-01-01
    相关资源
    最近更新 更多