• 【python】(十六)python内置库——logging



    官方文档说明https://docs.python.org/zh-cn/3/howto/logging.html

    1. 日志基础用法

    1.1 日志作用

    • 调试
    • 辅助定位问题
    • 数据分析

    1.2 日志的级别

    级别从低到高

    级别何时使用
    DEBUG细节信息,仅当诊断问题时使用。
    INFO确认程序按预期运行。
    WARNING表明有已经或者即将发生的意外(例如:磁盘空间不足)。程序仍然按照预期进行。
    ERROR由于严重的问题,程序的某些功能已经不能正常执行。
    CRITICAL严重的错误,表明程序已经不能继续执行。

    1.3 日志的用法

    1.3.1 日志模块常用函数

    函数说明
    logging.debug(msg,*args,**kwargs)创建一条严重级别为DEBUG的日志记录
    logging.info(msg,*args,**kwargs)创建一条严重级别为INFO的日志记录
    logging.warning(msg,*args,**kwargs)创建一条严重级别为WARNING的日志记录
    logging.error(msg,*args,**kwargs)创建一条严重级别为ERROR的日志记录
    logging.critical(msg,*args,**kwargs)创建一条严重级别为CRITICAL的日志记录
    logging.log(level,*args,**kwargs)创建一条严重级别为Level的日志记录
    logging.basicConfig(**kwargs)对 root logger进行一次性配置

    注:logging默认日志级别是warning。根据定义的级别,打印当前级别及以上级别的日志,比如:定义的是warning的话,则会打印warning及其以上级别的日志,即warning、error、critical级别。

    basicConfig 一定要定义在代码最前面,因为basiConfig只执行一次,并且没有累加的效果。如果设置再后面,只对basicConfig之后的代码生效,之前的无效。

    示例:

    import logging
    #logging默认设置的界别是warning
    logging.warning('Watch out!')  # will print a message to the console
    logging.info('I told you so')  # will not print anything
    logging.error('This a Error.')
    
    """
    打印结果:
    WARNING:root:Watch out!
    ERROR:root:This a Error.
    """
    #只打印了warning和warning以上的error级别的日志。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.3.2 设置日志级别

    import logging
    #把日志级别设置成INFO级别。
    logging.basicConfig(level=logging.INFO)
    #日志设置成哪个级别,就会打印哪个级别及其以上级别的日志。
    
    logging.debug('This is a Debug.')
    logging.warning('Watch out!')  
    logging.info('I told you so') 
    logging.error('This a Error.')
    
    """
    打印结果:
    WARNING:root:Watch out!
    INFO:root:I told you so
    ERROR:root:This a Error.
    """
    #打印了INFO及以上级别的日志,Debug没有被打印。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1.3.3 将日志保存到文件中

    使用logging.basicConfig()中的filename参数来确定日志文件的名称和日志保存的位置。

    import logging
    #filename参数确认日志名称和保存位置
    logging.basicConfig(filename="example.log",level=logging.DEBUG)
    logging.debug('This message should go to the log file')
    logging.info('So should this')
    logging.warning('And this, too')
    logging.error('And non-ASCII stuff, too, like Øresund and Malmö')
    
    """
    example.log文件中记录的结果:
    DEBUG:root:This message should go to the log file
    INFO:root:So should this
    WARNING:root:And this, too
    ERROR:root:And non-ASCII stuff, too, like \xd8resund and Malm\xf6
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    1.3.4 设置日志中的时间格式

    使用logging.basicConfig()函数中的format参数来确定日志信息的格式,datefmt参数来确定日期的格式。

    import logging
    logging.basicConfig(filename="example.log",format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p',level=logging.DEBUG)
    logging.debug('This message should go to the log file')
    logging.info('So should this')
    logging.warning('And this, too')
    logging.error('And non-ASCII stuff, too, like Øresund and Malmö')
    
    """
    example.log文件中记录的结果:
    09/09/2022 10:58:58 AM This message should go to the log file
    09/09/2022 10:58:58 AM So should this
    09/09/2022 10:58:58 AM And this, too
    09/09/2022 10:58:58 AM And non-ASCII stuff, too, like \xd8resund and Malm\xf6
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. format='%(asctime)s %(message)s'

    %(asctime)s:表示人类易读的LogRecord生成时间。 默认形式为 ‘2003-07-08 16:49:45,896’ (逗号之后的数字为时间的毫秒部分)。

    %(message)s:记入日志的消息.

    LogRecord属性格式化详细说明:https://docs.python.org/zh-cn/3/library/logging.html#logrecord-attributes

    1. datefmt='%m/%d/%Y %I:%M:%S %p'

    %m/%d/%Y %I:%M:%S %p时间格式化显示为:月/日/年 小时(12小时制的小时):分钟:秒

    时间格式化详细说明: https://docs.python.org/zh-cn/3/library/time.html#time.strftime

    1.3.5 日志格式优化

    日志内容中打印级别,文件名和行号

    import logging
    #在format参数中将日志打印格式丰富,添加了日志界别,代码文件名和代码行号
    logging.basicConfig(filename="example.log",format='%(asctime)s [%(levelname)s]: %(message)s  (%(filename)s:%(lineno)s)', datefmt='%m/%d/%Y %I:%M:%S %p',level=logging.DEBUG)
    logging.debug('This message should go to the log file.')
    logging.info('So should this.')
    logging.warning('And this, too.')
    logging.error('And non-ASCII stuff, too, like Øresund and Malmö.')
    
    """
    example.log文件中记录的结果:
    09/09/2022 11:16:13 AM [DEBUG]: This message should go to the log file.  (demo.py:3)
    09/09/2022 11:16:13 AM [INFO]: So should this.  (demo.py:4)
    09/09/2022 11:16:13 AM [WARNING]: And this, too.  (demo.py:5)
    09/09/2022 11:16:13 AM [ERROR]: And non-ASCII stuff, too, like \xd8resund and Malm\xf6.  (demo.py:6)
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2. 日志进阶用法

    2.1 日志记录流程

    2.1.1 日志组件

    组件说明
    loggers(记录器)提供应用程序代码直接使用的接口
    handlers(处理器)用于将日志记录发送到指定的目的位置
    filters(过滤器)提供更细粒度的日志过滤功能,用于决定哪些日志记录将会被输出(其他日志记录将会被忽略)
    formatters(格式器)用于控制日志信息的最终输出格式

    2.1.2 日志记录流程图

    在这里插入图片描述

    2.1.3 示例

    示例1:将日志信息输出至终端

    import logging
    
    # 创建一个记录器
    logger = logging.getLogger('simple_example')
    logger.setLevel(logging.DEBUG)
    
    # 创建一个处理器,将消息输出到终端中
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    
    # 创建格式器
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    # 把格式器放到处理器
    ch.setFormatter(formatter)
    
    # 把处理器放到记录器中
    logger.addHandler(ch)
    
    # 'application' code
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warn message')
    logger.error('error message')
    logger.critical('critical message')
    
    
    """
    终端打印内容:
    2022-09-09 11:43:00,388 - simple_example - DEBUG - debug message
    2022-09-09 11:43:00,388 - simple_example - INFO - info message
    2022-09-09 11:43:00,388 - simple_example - WARNING - warn message
    2022-09-09 11:43:00,388 - simple_example - ERROR - error message
    2022-09-09 11:43:00,389 - simple_example - CRITICAL - critical message
    """
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    示例2:将日志输出至文件

    import logging
    
    # 创建一个记录器
    logger = logging.getLogger('simple_example')
    logger.setLevel(logging.DEBUG)
    
    # 创建一个处理器,将消息输出到文件中
    ch = logging.FileHandler(filename='logger_demo.log',encoding='UTF-8')
    ch.setLevel(logging.DEBUG)
    
    # 创建格式器
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    # 把格式器放到处理器
    ch.setFormatter(formatter)
    
    # 把处理器放到记录器中
    logger.addHandler(ch)
    
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warn message')
    logger.error('error message')
    logger.critical('critical message')
    
    """
    终端中未输出内容,输出到文件中。
    文件中输出内容:
    2022-09-09 11:45:44,390 - simple_example - DEBUG - debug message
    2022-09-09 11:45:44,390 - simple_example - INFO - info message
    2022-09-09 11:45:44,390 - simple_example - WARNING - warn message
    2022-09-09 11:45:44,391 - simple_example - ERROR - error message
    2022-09-09 11:45:44,391 - simple_example - CRITICAL - critical message
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    示例3:将日志输出到文件中和终端中

    一个记录器可以同时有多个处理器。

    import logging
    
    # 创建一个记录器
    logger = logging.getLogger('simple_example')
    logger.setLevel(logging.DEBUG)
    
    # 创建一个处理器,将消息输出到文件中
    ch = logging.FileHandler(filename='logger_demo.log',encoding='UTF-8')
    ch.setLevel(logging.DEBUG)
    
    # 创建一个处理器,将消息输出到终端
    ch1 = logging.StreamHandler()
    ch1.setLevel(logging.DEBUG)
    
    # 创建格式器
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    # 把格式器放到处理器
    ch.setFormatter(formatter)
    ch1.setFormatter(formatter)
    
    # 把处理器放到记录器中
    logger.addHandler(ch)
    logger.addHandler(ch1)
    
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warn message')
    logger.error('error message')
    logger.critical('critical message')
    
    """
    文件和终端都有日志输出。
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    2.2 封装日志公共模块

    封装日志公共模块后,更加方便代码开发与调用。

    import logging
    import os
    
    #定义一个记录器
    def get_logger():
        # 定义了记录器
        logger = logging.getLogger(os.path.basename(__file__))
        logger.setLevel(logging.DEBUG)
        # 定义了一个处理器
        ch = logging.FileHandler(filename='mylog.log', encoding="utf-8")
        ch.setLevel(logging.DEBUG)
        # 定义了一个格式器
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        # 将格式器加入处理器中
        ch.setFormatter(formatter)
        # 将处理器加入记录器中
        logger.addHandler(ch)
        return  logger
    
    #封装一个info级别方法
    def log_info(message):
        logger.info(message)
    
    #声明一个get_logger对象
    logger=get_logger()
    
    #使用封装的方法输入info级别日志
    log_info('info message')
    logger.debug('debug message')
    logger.warning('warn message')
    logger.error('error message')
    logger.critical('critical message')
    
    """
    日志文件中输出内容:
    2022-09-09 13:57:33,066 - demo.py - INFO - info message
    2022-09-09 13:57:33,067 - demo.py - DEBUG - debug message
    2022-09-09 13:57:33,067 - demo.py - WARNING - warn message
    2022-09-09 13:57:33,068 - demo.py - ERROR - error message
    2022-09-09 13:57:33,069 - demo.py - CRITICAL - critical message
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    2.3 日志配置文件logging.conf

    示例:

    1. logging.conf文件

    注意:Windows系统下,conf文件中不能包含中文字符,否者会报错。

    [loggers] # loggers 对象列表。root必须要有,他是一个根节点的值。
    keys=root,main
    
    [handlers] # handlers 对象列表
    keys=consoleHandlers,fileHandlers
    
    [formatters] # formatters 对象列表
    keys=fmt
    
    [logger_root]
    level=DEBUG
    handlers=consoleHandlers,fileHandlers
    
    [logger_main] # main logger
    level = DEBUG
    handlers = fileHandlers
    qualname=main  #定义logger需要的名称,一般和前面一致
    propagate=0
    
    [handler_consoleHandlers] # consoleHandlers 指定控制器的输出方向、级别、输出格式、参数
    class = StreamHandler
    level = DEBUG
    formatter = fmt
    args = (sys.stdout,)
    
    [handler_fileHandlers] # 循环日志文件
    class = logging.handlers.RotatingFileHandler
    level = DEBUG
    formatter = fmt
    args = ('./logs/test.log', 'a', 10000, 3, 'UTF-8') # 以文件大小来分割,每隔 1000 Byte 划分一个日志文件,备份文件为 3 个
    
    [formatter_fmt]  # fmt 格式
    format=%(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s)
    datefmt=
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    1. 测试代码:
    import logging.config
    
    logging.config.fileConfig('logging.conf')
    logger=logging.getLogger("main")
    logger.debug("这是一个debug的问题")
    
    """
    logs/test.log内容:
    2022-09-09 14:15:09,100 [DEBUG] 这是一个debug的问题 (demo.py:5)
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    IOS17正式版今日发布
    小知识·认识CMake
    kafka 自定义Interceptor(通过拦截器对消息进行定制化处理)
    linux总结10大危险命令
    快速学习nginx反向代理
    WPF透明置顶窗口wine适配穿透问题解决
    python学习笔记:第九章异常
    浙大恩特客户资源管理系统CustomerAction.entphone;.js 接口任意文件上传漏洞复现 [附POC]
    Vue路由(vue-router)
    点云从入门到精通技术详解100篇-基于深度学习的三维植物点云分割网络
  • 原文地址:https://blog.csdn.net/gjj920318/article/details/126855364