zoukankan      html  css  js  c++  java
  • Python(00):logging日志模块

    一、概述

    1、步骤

    • 创建logger对象
    • 创建handler对象
    • 创建formatter对象
    • 把formatter绑定到handler对象上
    • 把handler对象绑定到logger对象上
    • 设置级别
    • 测试

    二、低配logging

    日志总共分为以下五个级别,这个五个级别自下而上进行匹配 debug-->info-->warning-->error-->critical,默认最低级别为warning级别。

    critical=50、error =40 、arning =30、info = 20、debug =10

    v1:屏幕输出

    v1版本无法指定日志的级别;无法指定日志的格式;只能往屏幕打印,无法写入文件。

    import logging
    
    logging.debug('调试信息')
    logging.info('正常信息')
    logging.warning('警告信息')  # WARNING:root:警告信息
    logging.error('报错信息')  # ERROR:root:报错信息
    logging.critical('严重错误信息')  # CRITICAL:root:严重错误信息

    v2:输出到文件

    v2版本不能指定字符编码;只能往文件中打印。

    可在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:

    • filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
    • filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
    • format:指定handler使用的日志显示格式。
    • datefmt:指定日期时间格式。
    • level:设置rootlogger(后边会讲解具体概念)的日志级别
    • stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
    import logging
    # 日志的基本配置
    
    logging.basicConfig(filename='access.log',
                        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S %p',
                        level=10)
    
    logging.debug('调试信息')  #  2019-11-28 18:25:26 PM - root - DEBUG -run: 调试信息
    logging.info('正常信息')  #  2019-11-28 18:25:26 PM - root - INFO -run: 正常信息
    logging.warning('警告信息')  #  2019-11-28 18:25:26 PM - root - WARNING -run: 警告信息
    logging.error('报错信息')  #  2019-11-28 18:25:26 PM - root - ERROR -run: 报错信息
    logging.critical('严重错误信息')  #  2019-11-28 18:25:26 PM - root - CRITICAL -run: 严重错误信息

    format参数中可能用到的格式化串:

    • %(name)s :Logger的名字
    • %(levelno)s :数字形式的日志级别
    • %(levelname)s :文本形式的日志级别
    • %(pathname)s 调:用日志输出函数的模块的完整路径名,可能没有
    • %(filename)s :调用日志输出函数的模块的文件名
    • %(module)s :调用日志输出函数的模块名
    • %(funcName)s :调用日志输出函数的函数名
    • %(lineno)d :调用日志输出函数的语句所在的代码行
    • %(created)f :当前时间,用UNIX标准的表示时间的浮 点数表示
    • %(relativeCreated)d :输出日志信息时的,自Logger创建以 来的毫秒数
    • %(asctime)s :字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    • %(thread)d :线程ID。可能没有
    • %(threadName)s :线程名。可能没有
    • %(process)d :进程ID。可能没有
    • %(message)s:用户输出的消息

    v3:使用内置各种对象

    logging模块包含四种角色:logger、Filter、Formatter、Handler对象

    1. logger:产生日志的对象
    2. Filter:过滤日志的对象
    3. Formatter:可以定制不同的日志格式对象,然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式
    4. Handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端
    import logging
    
    # 1、logger对象:负责产生日志,然后交给Filter过滤,然后交给不同的Handler输出
    logger = logging.getLogger(__file__)
    
    # 2、Filter对象:不常用,略
    
    # 3、Handler对象:接收logger传来的日志,然后控制输出
    h1 = logging.FileHandler('t1.log')  # 打印到文件
    h2 = logging.FileHandler('t2.log')  # 打印到文件
    sm = logging.StreamHandler()  # 打印到终端
    
    # 4、Formatter对象:日志格式
    formmater1 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
                                   datefmt='%Y-%m-%d %H:%M:%S %p', )
    formmater2 = logging.Formatter('%(asctime)s :  %(message)s',
                                   datefmt='%Y-%m-%d %H:%M:%S %p', )
    formmater3 = logging.Formatter('%(name)s %(message)s', )
    
    # 5、为Handler对象绑定格式
    h1.setFormatter(formmater1)
    h2.setFormatter(formmater2)
    sm.setFormatter(formmater3)
    
    # 6、将Handler添加给logger并设置日志级别
    logger.addHandler(h1)
    logger.addHandler(h2)
    logger.addHandler(sm)
    
    # 设置日志级别,可以在两个关卡进行设置logger与handler
    # logger是第一级过滤,然后才能到handler
    logger.setLevel(30)
    h1.setLevel(10)
    h2.setLevel(10)
    sm.setLevel(10)
    
    # 7、测试
    logger.debug('debug')
    logger.info('info')
    logger.warning('warning')
    logger.error('error')
    logger.critical('critical')

    三、高配logging

    1、 配置日志文件

    以上三个版本的日志只是为了引出我们下面的日志配置文件

    import os
    import logging.config
    
    # 定义三种日志输出格式 开始
    standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' 
                      '[%(levelname)s][%(message)s]'  # 其中name为getLogger()指定的名字;lineno为调用日志输出函数的语句所在的代码行
    simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
    id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
    # 定义日志输出格式 结束
    
    logfile_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # log文件的目录,需要自定义文件路径 # atm
    logfile_dir = os.path.join(logfile_dir, 'log')  # C:UsersoldboyDesktopatmlog
    
    logfile_name = 'log.log'  # log文件名,需要自定义路径名
    
    # 如果不存在定义的日志目录就创建一个
    if not os.path.isdir(logfile_dir):  # C:UsersoldboyDesktopatmlog
        os.mkdir(logfile_dir)
    
    # log文件的全路径
    logfile_path = os.path.join(logfile_dir, logfile_name)  # C:UsersoldboyDesktopatmloglog.log
    # 定义日志路径 结束
    
    # log配置字典
    LOGGING_DIC = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': standard_format
            },
            'simple': {
                'format': simple_format
            },
        },
        'filters': {},  # filter可以不定义
        'handlers': {
            # 打印到终端的日志
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',  # 打印到屏幕
                'formatter': 'simple'
            },
            # 打印到文件的日志,收集info及以上的日志
            'default': {
                'level': 'INFO',
                'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
                'formatter': 'standard',
                'filename': logfile_path,  # 日志文件
                'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M  (*****)
                'backupCount': 5,
                'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
            },
        },
        'loggers': {
            # logging.getLogger(__name__)拿到的logger配置。如果''设置为固定值logger1,则下次导入必须设置成logging.getLogger('logger1')
            '': {
                # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                'handlers': ['default', 'console'],
                'level': 'DEBUG',
                'propagate': False,  # 向上(更高level的logger)传递
            },
        },
    }
    
    
    
    def load_my_logging_cfg():
        logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
        logger = logging.getLogger(__name__)  # 生成一个log实例
        logger.info('It works!')  # 记录该文件的运行状态
        
        return logger
    
    
    if __name__ == '__main__':
        load_my_logging_cfg()

    2、 使用日志

    import time
    import logging
    import my_logging  # 导入自定义的logging配置
    
    logger = logging.getLogger(__name__)  # 生成logger实例
    
    
    def demo():
        logger.debug("start range... time:{}".format(time.time()))
        logger.info("中文测试开始。。。")
        for i in range(10):
            logger.debug("i:{}".format(i))
            time.sleep(0.2)
        else:
            logger.debug("over range... time:{}".format(time.time()))
        logger.info("中文测试结束。。。")
    
    
    if __name__ == "__main__":
        my_logging.load_my_logging_cfg()  # 在你程序文件的入口加载自定义logging配置
        demo()

    四、Django日志配置文件

    Django(发音:[`dʒæŋɡəʊ])是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。

    # logging_config.py
    
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
                          '[%(levelname)s][%(message)s]'
            },
            'simple': {
                'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
            },
            'collect': {
                'format': '%(message)s'
            }
        },
        'filters': {
            'require_debug_true': {
                '()': 'django.utils.log.RequireDebugTrue',
            },
        },
        'handlers': {
            # 打印到终端的日志
            'console': {
                'level': 'DEBUG',
                'filters': ['require_debug_true'],
                'class': 'logging.StreamHandler',
                'formatter': 'simple'
            },
            # 打印到文件的日志,收集info及以上的日志
            'default': {
                'level': 'INFO',
                'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
                'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"),  # 日志文件
                'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
                'backupCount': 3,
                'formatter': 'standard',
                'encoding': 'utf-8',
            },
            # 打印到文件的日志:收集错误及以上的日志
            'error': {
                'level': 'ERROR',
                'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
                'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"),  # 日志文件
                'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
                'backupCount': 5,
                'formatter': 'standard',
                'encoding': 'utf-8',
            },
            # 打印到文件的日志
            'collect': {
                'level': 'INFO',
                'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
                'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"),
                'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
                'backupCount': 5,
    
                'formatter': 'collect',
                'encoding': "utf-8"
            }
        },
        'loggers': {
            # logging.getLogger(__name__)拿到的logger配置
            '': {
                'handlers': ['default', 'console', 'error'],
                'level': 'DEBUG',
                'propagate': True,
            },
            # logging.getLogger('collect')拿到的logger配置
            'collect': {
                'handlers': ['console', 'collect'],
                'level': 'INFO',
            }
        },
    }
    
    
    # -----------
    # 用法:拿到俩个logger
    
    logger = logging.getLogger(__name__)  # 线上正常的日志
    collect_logger = logging.getLogger("collect")  # 领导说,需要为领导们单独定制领导们看的日志
  • 相关阅读:
    mac c++编译出现segmentation fault :11错误
    ssh 连接缓慢解决方法
    237. Delete Node in a Linked List
    203. Remove Linked List Elements
    Inversion of Control Containers and the Dependency Injection pattern
    82. Remove Duplicates from Sorted List II
    83. Remove Duplicates from Sorted List
    SxsTrace
    使用CCleaner卸载chrome
    decimal and double ToString problem
  • 原文地址:https://www.cnblogs.com/springsnow/p/12558335.html
Copyright © 2011-2022 走看看