• python logging模块


    logging模块的使用方式


    logging模块提供了两种记录日志的方式:

    • 第一种是logging提供的模块级别函数
    • 第二种是使用Logging日志系统的四大组件

    其实,logging所提供的模块级别的日志记录函数也是对logging日志系统相关类的封装而已。


    一、使用logging提供的模块级别函数

    # coding: utf-8
    
    """
    使用模块级别的函数记录日志
    配置logging.basicConfig函数,把日志输出到文件
    """
    
    import logging
    import os
    
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    LOG_FILE_PATH = os.path.join(BASE_DIR, "my.log")
    
    LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
    
    # 不提供filename则默认输出到控制台
    logging.basicConfig(filename=LOG_FILE_PATH, level=logging.DEBUG, format=LOG_FORMAT)
    
    logging.debug("This is a debug log.")
    logging.info("This is a info log.")
    logging.warning("This is a warning log.")
    logging.error("This is a error log.")
    logging.critical("This is a critical log.")
    View Code

     1、logging.basicConfig(**kwargs)函数说明

    参数名称描述
    filename 指定日志输出目标文件的文件名,指定该设置后日志信息就不会被输出到控制台了
    filemode 指定日志文件的打开模式,默认为'a'。需要注意的是,该选项要在filename指定时才有效
    format 指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。logging模块定义的格式字段下面会列出。
    datefmt 指定日期/时间格式。需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效
    level 指定日志器的日志级别
    stream 指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream。需要说明的是,stream和filename不能同时提供,否则会引发 ValueError异常
    style Python 3.2中新添加的配置项。指定format格式字符串的风格,可取值为'%'、'{'和'$',默认为'%'
    handlers Python 3.3中新添加的配置项。该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常。


    2、logging模块定义的格式字符串 

    字段/属性名称使用格式描述
    asctime %(asctime)s 日志事件发生的时间--人类可读时间,如:2003-07-08 16:49:45,896
    created %(created)f 日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值
    relativeCreated %(relativeCreated)d 日志事件发生的时间相对于logging模块加载时间的相对毫秒数(目前还不知道干嘛用的)
    msecs %(msecs)d 日志事件发生事件的毫秒部分
    levelname %(levelname)s 该日志记录的文字形式的日志级别('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
    levelno %(levelno)s 该日志记录的数字形式的日志级别(10, 20, 30, 40, 50)
    name %(name)s 所使用的日志器名称,默认是'root',因为默认使用的是 rootLogger
    message %(message)s 日志记录的文本内容,通过 msg % args计算得到的
    pathname %(pathname)s 调用日志记录函数的源码文件的全路径
    filename %(filename)s pathname的文件名部分,包含文件后缀
    module %(module)s filename的名称部分,不包含后缀
    lineno %(lineno)d 调用日志记录函数的源代码所在的行号
    funcName %(funcName)s 调用日志记录函数的函数名
    process %(process)d 进程ID
    processName %(processName)s 进程名称,Python 3.1新增
    thread %(thread)d 线程ID
    threadName %(threadName)s 线程名称

    logging.info("name: %s" % "Mikle")和logging.info("name: %s", "Mikle")这两种是一样的,因为message是通过msg % args计算得到的。

    3、logging日志级别

    日志等级(level)描述
    DEBUG 最详细的日志信息,典型应用场景是 问题诊断
    INFO 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作
    WARNING 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
    ERROR 由于一个更严重的问题导致某些功能不能正常运行时记录的信息
    CRITICAL 当发生严重错误,导致应用程序不能继续运行时记录的信息

    二、logging四大组件

    组件名称对应类名功能描述
    日志器 Logger 提供了应用程序可一直使用的接口
    处理器 Handler 将logger创建的日志记录发送到合适的目的输出
    过滤器 Filter 提供了更细粒度的控制工具来决定输出哪条日志记录,丢弃哪条日志记录
    格式器 Formatter 决定日志记录的最终输出格式

    logging组件记录日志流程

    1. 定义日志器对象logger
    2. 设置日志器对象的日志等级,log等级总开关
    3. 定义处理器对象handler,一个logger可以对应多个处理器对象
    4. 定义格式器对象Formatter
    5. 把格式器对象添加到处理器对象
    6. 把处理器对象添加到日志器对象
    # coding: utf-8
    
    """
    1)将所有级别的所有日志都写入磁盘文件中
    2)all.log文件中记录所有的日志信息,日志格式为:日期和时间 - 日志级别 - 日志信息
    3)error.log文件中单独记录error及以上级别的日志信息,日志格式为:日期和时间 - 日志级别 - 文件名[:行号] - 日志信息
    4)要求all.log在每天凌晨进行日志切割(TimedRotatingFileHandler)
    """
    
    import logging
    import logging.handlers
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    
    # 1、TimedRotatingFileHandler
    rf_handler = logging.handlers.TimedRotatingFileHandler('all.log', when='midnight', interval=1, backupCount=7)
    fmt = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    rf_handler.setFormatter(fmt)
    
    # 2、FileHandler
    f_handler = logging.FileHandler('error.log')
    f_handler.setLevel(logging.ERROR)
    fmt2 = logging.Formatter("%(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s")
    f_handler.setFormatter(fmt2)
    
    logger.addHandler(rf_handler)
    logger.addHandler(f_handler)
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warning message')
    logger.error('error message')
    logger.critical('critical message')
    View Code
    以下代码可以直接使用,把代码保存为log.py,然后import log就可以直接使用了。
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    """
    log模块第一次导入的时候,是作为一个文件被查找到的。查找成功后,文件会跑一个生成log实例的逻辑,然后把它加入到全局sys.modules字典里面。
    以后所有模块的`import log`动作都会绕开文件查找的过程,直接在sys.modules里面找这个模块。
    """
    """
    可以直接使用
    import log
    
    log.info()
    log.error()
    ...
    """
    
    import os
    import sys
    import logging
    import logging.handlers
    
    # 当前目录下会生成对应的log文件
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    ACCESS_LOG_PATH = os.path.join(BASE_DIR, "access.log")
    ERROR_LOG_PATH = os.path.join(BASE_DIR, "error.log")
    
    class Log(object):                                                                                                                                                   [0/708]
    
        ACCESS_LOG_PATH = ACCESS_LOG_PATH
        ERROR_LOG_PATH = ERROR_LOG_PATH
        FMT = (
            '[%(levelname)s][%(name)s:%(process)d][%(asctime)s]' +
            ': %(message)s')
    
        def __init__(self, name):
            logger = logging.getLogger(name)
    
            fmt = logging.Formatter(self.FMT)
    
            trf_handler = logging.handlers.TimedRotatingFileHandler(
                self.ACCESS_LOG_PATH, 'D', 1, 7)
            trf_handler.setLevel(logging.INFO)
            trf_handler.setFormatter(fmt)
    
            rf_handler = logging.handlers.RotatingFileHandler(
                self.ERROR_LOG_PATH,
                maxBytes=1024*1024, backupCount=5)
            rf_handler.setLevel(logging.ERROR)
            rf_handler.setFormatter(fmt)
    
            logger.addHandler(trf_handler)
            logger.addHandler(rf_handler)
    
            self.logger = logger
    
        def __call__(self):
            return self.logger
    
    
    sys.modules[__name__] = Log(__name__)()
    View Code

     RotatingFileHandler

    日志回滚

    比如日志文件是chat.log,当chat.log达到指定的大小之后,RotatingFileHandler自动把文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。最后重新创建 chat.log,继续输出日志信息。【这样保证了chat.log里面是最新的日志】
    (原文链接:https://blog.csdn.net/chpllp/article/details/72649506)

    RotatingFileHandler参数说明

    def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0)

    参数描述
    filename log文件名
    mode 写入日志文件的模式,默认'a',追加
    maxBytes

    日志文件大小,即大于多少时切割日志。如果是0,则不切割。

    比如50M,maxBytes=1024*1024*50

    backupCount 文件备份数量,比如日志文件是chat.log,当chat.log达到指定大小后,RotatingFileHandler自动把文件改名为chat.log.1,如果backupCount=5,则文件名一直到chat.log.5
    encoding 写入日志编码,默认None
    delay 写入log文件的延迟时间,默认0

    TimedRotatingFileHandler

    按时间切割日志

    TimedRotatingFileHandler参数说明

    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False)

    参数描述
    filename log文件名
    when

    切割日志的时间

    "S": 每秒

    "M": 每分钟

    "H": 每小时

    "D": 每天(每天的0:00)

    "MIDNIGHT": 与"D"相同

    "W{0~6}": 每个星期,W0 表示周日

    when参数忽略大小写,即用大小写都行,因为参数会先upper()转换成大写。用"M"和"m"是相同的。

    interval

    间隔,间隔多少个when执行一次。如果when="D", interval=2,则每隔两天切割一次。默认1。

    backupCount 备份数量,备份的log文件后缀会跟上时间
    encoding 写入日志编码,默认None
    delay 写入log文件的延迟时间,默认0
    utc  当when是"D"或"W{0~6}"时,是否以UTC的时间来切割,默认False,表示本地时间。

    RotatingFileHandler存在的问题 

    https://www.jianshu.com/p/1772306cb3db?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

    参考文档

    https://www.cnblogs.com/yyds/p/6901864.html

  • 相关阅读:
    tcpdump使用技巧
    linux: 系统调用
    linux命令:rsync, 同步文件和文件夹的命令
    编译kernel:make Image uImage与zImage的区别
    linux下操作gpio寄存器的方法
    Linux输入子系统(Input Subsystem)
    Android电源管理基础知识整理
    【Android休眠】之Android休眠机制
    拓扑排序入门(真的很简单)
    有向无环图的拓扑排序
  • 原文地址:https://www.cnblogs.com/shengmading/p/14737482.html
Copyright © 2020-2023  润新知