zoukankan      html  css  js  c++  java
  • Python-logging模块实现同时向控制台和文件打印日志

    Python-logging模块实现同时向控制台和文件打印日志

    前言

    在写我自己的练手项目的时候,需要写一系列Python脚本来帮助我进行运维/环境配置,我希望这些脚本能够有比较好的日志记录。

    一方面我希望其能够直接打印到控制台,方便我实时查看,另一方面我也希望能够记录到日志文件中,这样能够方便我日后翻旧账。

    更进一步,我希望控制台输出比较重要的信息,让我的控制台不至于太乱,而日志文件中我希望能够尽量详细。

    本博客中,我实现了日志同时向控制台和日志中进行输出,并且二者的日志等级、日志格式不相同。

    参考

    basicConfig

    参考Python 官方文档 | logging模块#basicConfig

    这个函数对logging模块的日志记录器进行基本配置,无论我们直接通过logging.info(msg)进行日志记录,还是我们先通过logging.getLogger(name)获取一个logger再进行日志记录,通过basicConfig函数加入的配置都会生效。

    值得注意的是,因为有些操作会导致basicConfig函数被自动调用,所以我们尽量在程序开始时尽早进行调用。

    我们需要关注的是basicConfighandlers参数。

    handler

    如果说logger是面向上层开发者的接口,那么handler就是面向底层的执行者。开发者通过调用logger的方法来输出日志,而logger通过handler将日志进行实际的记录。

    一个logger可以有若干handler,logger和handler都可以有一个日志等级。当记录等级高于logger的日志时,logger会通知每一个handler对该日志进行记录,而每一个handler记录会通过该条日志的等级和handler的等级进行比较,当日志等级高于handler等级的时候,才会进行记录。

    handler主要位于logging.handler包下,我们这次需要使用StreamHandler以及其子类FileHandler

    实现

    通过前面的分析,思路已经很清晰了:

    1. 创建两个handler,其中一个向控制台进行输出,一个向文件进行输出;
    2. 为这两个handler配置不同的日志等级和日志格式;
    3. 通过basicConfig函数来将这两个handler添加到全局日志的默认配置;

    以下为实现:

    import logging
    import sys
    
    def config_logging(file_name: str, console_level: int=logging.INFO, file_level: int=logging.DEBUG):
        file_handler = logging.FileHandler(file_name, mode='a', encoding="utf8")
        file_handler.setFormatter(logging.Formatter(
            '%(asctime)s [%(levelname)s] %(module)s.%(lineno)d %(name)s:	%(message)s'
            ))
        file_handler.setLevel(file_level)
    
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(logging.Formatter(
            '[%(asctime)s %(levelname)s] %(message)s',
            datefmt="%Y/%m/%d %H:%M:%S"
            ))
        console_handler.setLevel(console_level)
    
        logging.basicConfig(
            level=min(console_level, file_level),
            handlers=[file_handler, console_handler],
            )
    
    if __name__ == '__main__':
        config_logging("test.log", logging.WARNING, logging.DEBUG)
        logging.debug("debug")
        logging.info("info")
        logging.warning("warning")
        logging.critical("critical")
    
        logger = logging.getLogger(__name__)
        logger.debug("debug")
        logger.info("info")
        logger.warning("warning")
        logger.critical("critical")
    

    关键是config_logging函数,这个函数进行了基本的配置,我们只需要在程序的入口处先调用这个函数就能完成全局的日志配置。

    需要注意的是在调用logging.basicConfig时,我们需要设置level=min(console_level, file_level),这是因为这个参数设置的是logger的等级,如果一条日志已经被logger过滤掉了,那么handler的等级设置的再低也不会进行记录。直接level=logging.DEBUGlevel=0应该也可以,但是我认为比所有handler的等级都低的日志是不会进行输出的,与其让这条日志到了handler这一步才被过滤,不如直接就在logger这一步就将其过滤掉。

    关于Formatter相关的操作,请看下一篇博客

  • 相关阅读:
    常见加密算法概述
    IDEA常见错误解决
    linux Find命令教程
    用注册表更改DNS的代码分享
    关于javascript中的typeof和instanceof介绍
    javascript instanceof,typeof的区别
    Javascript typeof 用法
    浅析JavaScript中的typeof运算符
    玩转Linux文件描述符和重定向
    shell脚本 批量转换目录下文件编码
  • 原文地址:https://www.cnblogs.com/SnowPhoenix/p/15201097.html
Copyright © 2011-2022 走看看