logging.config 日志模块

logging 日志模块

简单应用:

import logging
logging.warning('警告!')  

# 输出结果:
WARNING:root:警告!

1. 日志等级

- debug   	调试 10 最详细的日志信息,典型应用场景是 问题诊断
- info    	普通信息 20 信息详细程度仅次于DEBUG,用于确认一切都是按照我们预期的那样进行工作
- warning 	警告信息 30 当某些不期望的事情发生时记录的信息,但是此时应用程序还是正常运行的
- error 	错误信息 40 由于一个更严重的问题导致某些功能不能正常运行时记录的信息
- critical	严重错误信息 50 当发生严重错误,导致应用程序不能继续运行时记录的信息

2. 日志形式

一条日志信息一般包括以下几点:

  • 事件发生的时间
  • 事件发生的位置
  • 事件的严重程度 – 日志级别(DEBUG -> INFO -> WARNING -> ERROR -> CRITICAL)
  • 事件的内容

2.1 logging模块的四大组件

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

这些组件之间的关系描述:

  • 不同的处理器(handler)可以将日志输出到不同的位置;
  • 日志器(logger)可以设置多个处理器(handler)将同一条日志记录输出到不同的位置;
  • 每个处理器(handler)都可以设置自己的过滤器(filter)实现日志过滤,从而只保留感兴趣的日志;
  • 每个处理器(handler)都可以设置自己的格式器(formatter)实现同一条日志以不同的格式输出到不同的地方。

简单点说就是:日志器(logger)是入口,真正干活儿的是处理器(handler),处理器(handler)还可以通过过滤器(filter)和格式器(formatter)对要输出的日志内容做过滤和格式化等处理操作。

2.1.1 Logger日志记录器

Logger对象有3个任务要做:

  • 向应用程序代码暴露几个方法,使应用程序可以在运行时记录日志消息;
  • 基于日志严重等级(默认的过滤设施)或filter对象来决定要对哪些日志进行后续处理;
  • 将日志消息传送给所有感兴趣的日志handlers。

Logger对象最常用的方法分为两类:配置方法消息发送方法

最常用的配置方法如下:

方法描述
Logger.setLevel()设置日志器将会处理的日志消息的最低严重级别
Logger.addHandler() 和 Logger.removeHandler()为该logger对象添加 和 移除一个handler对象
Logger.addFilter() 和 Logger.removeFilter()为该logger对象添加 和 移除一个filter对象

logger对象配置完成后,可以使用下面的方法来创建日志记录:

方法描述
Logger.debug(), Logger.info(), Logger.warning(), Logger.error(), Logger.critical()创建一个与它们的方法名对应等级的日志记录
Logger.exception()创建一个类似于Logger.error()的日志消息
Logger.log()需要获取一个明确的日志level参数来创建一个日志记录

一个Logger对象呢?一种方式是通过Logger类的实例化方法创建一个Logger类的实例,但是我们通常都是用第二种方式–logging.getLogger()方法。

logging.getLogger()方法有一个可选参数name,该参数表示将要返回的日志器的名称标识,如果不提供该参数,则其值为’root’。若以相同的name参数值多次调用getLogger()方法,将会返回指向同一个logger对象的引用。

多次使用注意不能创建多个logger,否则会出现重复输出日志现象。

2.1.2 Handler 日志处理器

Handler对象的作用是(基于日志消息的level)将消息分发到handler指定的位置(文件、网络、邮件等)。Logger对象可以通过addHandler()方法为自己添加0个或者更多个handler对象。比如,一个应用程序可能想要实现以下几个日志需求:

  • 1)把所有日志都发送到一个日志文件中;
  • 2)把所有严重级别大于等于error的日志发送到stdout(标准输出);
  • 3)把所有严重级别为critical的日志发送到一个email邮件地址。这种场景就需要3个不同的handlers,每个handler复杂发送一个特定严重级别的日志到一个特定的位置。
  Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
  Handler.setFormatter():给这个handler选择一个格式
  Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象

需要说明的是,应用程序代码不应该直接实例化和使用Handler实例。因为Handler是一个基类,它只定义了素有handlers都应该有的接口,同时提供了一些子类可以直接使用或覆盖的默认行为。下面是一些常用的Handler:

Handler描述
logging.StreamHandler将日志消息发送到输出到Stream,如std.out, std.err或任何file-like对象。
logging.FileHandler将日志消息发送到磁盘文件,默认情况下文件大小会无限增长
logging.handlers.RotatingFileHandler将日志消息发送到磁盘文件,并支持日志文件按大小切割
logging.hanlders.TimedRotatingFileHandler将日志消息发送到磁盘文件,并支持日志文件按时间切割
logging.handlers.HTTPHandler将日志消息以GET或POST的方式发送给一个HTTP服务器
logging.handlers.SMTPHandler将日志消息发送给一个指定的email地址
logging.NullHandler该Handler实例会忽略error messages,通常被想使用logging的library开发者使用来避免’No handlers could be found for logger XXX’信息的出现。
2.1.3 Formater 日志格式化

Formater对象用于配置日志信息的最终顺序、结构和内容。与logging.Handler基类不同的是,应用代码可以直接实例化Formatter类。另外,如果你的应用程序需要一些特殊的处理行为,也可以实现一个Formatter的子类来完成。

Formatter类的构造方法定义如下:

logging.Formatter.__init__(fmt=None, datefmt=None, style='%')

可见,该构造方法接收3个可选参数:

  • fmt:指定消息格式化字符串,如果不指定该参数则默认使用message的原始值
  • datefmt:指定日期格式字符串,如果不指定该参数则默认使用"%Y-%m-%d %H:%M:%S"
  • style:Python 3.2新增的参数,可取值为 ‘%’, ‘{‘和 ‘$’,如果不指定该参数则默认使用’%’

一般直接用logging.Formatter(fmt, datefmt)

日志格式参数:

 |  %(name)s            Name of the logger (logging channel) 记录器的名称
 |  %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
 |                      WARNING, ERROR, CRITICAL) 数字形式的日志记录级别
 |  %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
 |                      "WARNING", "ERROR", "CRITICAL") 日志记录级别的文本名称
 |  %(pathname)s        Full pathname of the source file where the logging
 |                      call was issued (if available) 执行日志记录调用的源文件的路径名称
 |  %(filename)s        Filename portion of pathname 执行日志记录调用的源文件的文件名称
 |  %(module)s          Module (name portion of filename) 执行日志记录调用的模块名称
 |  %(lineno)d          Source line number where the logging call was issued
 |                      (if available) 执行日志记录调用的行号
 |  %(funcName)s        Function name 执行日志记录调用的函数名称
 |  %(created)f         Time when the LogRecord was created (time.time()
 |                      return value) 执行日志记录的时间
 |  %(asctime)s         Textual time when the LogRecord was created 日期和时间
 |  %(msecs)d           Millisecond portion of the creation time 毫秒部分
 |  %(relativeCreated)d Time in milliseconds when the LogRecord was created,
 |                      relative to the time the logging module was loaded
 |                      (typically at application startup time)
 |  %(thread)d          Thread ID (if available) 线程ID
 |  %(threadName)s      Thread name (if available) 线程名称
 |  %(process)d         Process ID (if available) 进程ID
 |  %(message)s         The result of record.getMessage(), computed just as
 |                      the record is emitted 记录的消息

3. 日志记录一般流程

1、创建一个logger

2、设置下logger的日志的等级

3、创建合适的Handler(FileHandler要有路径)

4、设置下每个Handler的日志等级

5、创建下日志的格式

6、向Handler中添加上面创建的格式

7、将上面创建的Handler添加到logger中

8、打印输出logger.debug\logger.info\logger.warning\logger.error\logger.critical

3.1 示例

import os
import logging
from logging import StreamHandler, FileHandler, Formatter, Filter


def logs(*args):
    log_name, path, msg = args
    # 拼接写入路径和文件
    filename = os.path.join(path, '{}_log.txt'.format(log_name))
    # 设置日志名
    logger = logging.getLogger(log_name)
    # 设置记录器的信息等级:DEBUG -> INFO -> WARNING -> ERROR -> CRITICAL
    logger.setLevel(logging.INFO)  # 记录器可以记录INFO及以上等级信息

    # 创建日志处理器1
    handler1 = StreamHandler()   # 流处理器,标准输出控制台
    #  设置级别和格式
    handler1.setLevel(logging.INFO)
    handler1.setFormatter(Formatter(fmt='[ %(asctime)s - %(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S'))

    # 创建日志处理器2
    handler2 = FileHandler(filename, encoding='utf-8')   # 输出至文件
    handler2.setLevel(logging.INFO)
    handler2.setFormatter(Formatter(
        fmt="[ %(asctime)s - %(levelname)s > line %(lineno)s at %(pathname)s > ] %(message)s",
        datefmt='%Y-%m-%d %H:%M:%S'
    ))

    # 向记录器添加处理器
    logger.addHandler(handler1)
    logger.addHandler(handler2)

    # # 输出信息
    logger.info(msg)

    # return logger

if __name__ == '__main__':
    path = r'D:\02_project\Test\pingmesh'
    logs('om', path, '天气太热')

3.2 logging.config 实现日志记录

import os
import **logging.config**

def logging_config():
    # 定义字典
    LOGGING_CONFIG = {
        "version": 1,
        "disable_existing_logger": True,  # 删除已存在其他日志的Handler
        "formatters": {
            "standard": {
                # "format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
                "format": "{levelname} {asctime} {filename} ----> {message}",
                "style": "{",
            },
            "simple": {
                "format": "%(levelname)s  %(message)s",
                "style": "%",
            },
            "test": {
                "format": "$levelname  $message",
                "style": "$",
            },
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "formatter": "simple",
            },
            "sms_file": {
                "class": "logging.handlers.TimedRotatingFileHandler",
                "formatter": "standard",
                "filename": os.path.join('logs', 'sms.log'),
                "when": 'D',  # 根据天拆分日志
                "interval": 1,  # 1天
                "backupCount": 3,  # 备份个数
                "encoding": "utf-8",
            },
            # "error_file": {
            #     "class": "logging.handlers.TimedRotatingFileHandler",
            #     "formatter": "standard",
            #     "filename": os.path.join('logs', 'error.log'),
            #     "when": 'D',  # 根据天拆分日志
            #     "interval": 1,  # 1天
            #     "backupCount": 3,  # 备份个数
            #     "encoding": "utf-8",
            # },
        },
        "loggers": {
            "sms": {
                "handlers": ["sms_file", ],  # 意味着通过sms的loggers,写日志时, 级别 -> info 且 会写入到sms_file文件中
                "level": "INFO",
                "propagate": False  # 通过sms写日志时,同时也会找到他的父亲
            },
            # "error": {
            #     "handlers": ["error_file", ],
            #     "level": "ERROR",
            #     "propagate": True
            # },
        },
        # "root": {
        #     "handlers": ["console", ],
        #     "level": "ERROR",
        #     "propagate": True
        # },
    }

    #  2.根据自定义对logging进行配置
    logging.config.dictConfig(LOGGING_CONFIG)

    return logging


if __name__ == '__main__':
    logging = logging_config()
    # 3.写日志
    logger_object = logging.getLogger("sms")
    logger_object.info("今天太热了")

    # logger_object = logging.getLogger("error")
    # logger_object.error(666666)

注意:

存在一个问题:日志文件不能修改或删除,否则就无法继续记录日志

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将自定义的CustomTimedRotatingFileHandler类与logging.config.fileConfig()一起使用,需要进行以下步骤: 1. 创建一个配置文件,例如`logging.conf`,使用INI格式,并在其中定义你的日志配置。在配置文件中,使用`handler_class`参数来指定自定义的处理器类。 ```ini [loggers] keys=root [handlers] keys=custom_handler [formatters] keys=custom_formatter [logger_root] level=DEBUG handlers=custom_handler [handler_custom_handler] class=path.to.CustomTimedRotatingFileHandler level=DEBUG formatter=custom_formatter args=('example.log', 'midnight', 1, 0) [formatter_custom_formatter] format=%(asctime)s - %(levelname)s - %(message)s ``` 2. 在Python代码中,使用`logging.config.fileConfig()`函数加载配置文件: ```python import logging import logging.config logging.config.fileConfig('logging.conf') logger = logging.getLogger('root') logger.debug('This is a debug message') logger.info('This is an info message') logger.warning('This is a warning message') logger.error('This is an error message') logger.critical('This is a critical message') ``` 在上述代码中,`logging.config.fileConfig()`函数会读取指定的配置文件,并根据配置文件中的内容进行日志配置。配置文件中的`handler_custom_handler`部分定义了使用自定义的处理器类`CustomTimedRotatingFileHandler`,并将其应用于根日志记录器(`logger_root`)。 确保将`path.to.CustomTimedRotatingFileHandler`替换为实际的自定义处理器类的路径。同时,根据你的需求,可以在配置文件中调整处理器类的参数。 通过这种方式,你可以将自定义的处理器类与logging模块的配置机制相结合,灵活地配置和管理日志记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值