• python logging


    一:日志级别

    CRITICAL = 50
    FATAL = CRITICAL
    ERROR = 40
    WARNING = 30
    WARN = WARNING
    INFO = 20
    DEBUG = 10
    NOTSET = 0
    '
    运行

    二:日志格式化

    https://docs.python.org/3/library/logging.html#logrecord-attributes

    Attribute nameFormatDescription
    argsYou shouldn’t need to format this yourself.The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when there is only one argument, and it is a dictionary).
    asctime%(asctime)sHuman-readable time when the LogRecord was created. By default this is of the form 2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).
    created%(created)fTime when the LogRecord was created (as returned by time.time()).
    exc_infoYou shouldn’t need to format this yourself.Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
    filename%(filename)sFilename portion of pathname.
    funcName%(funcName)sName of function containing the logging call.
    levelname%(levelname)sText logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
    levelno%(levelno)sNumeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
    lineno%(lineno)dSource line number where the logging call was issued (if available).
    message%(message)sThe logged message, computed as msg % args. This is set when Formatter.format() is invoked.
    module%(module)sModule (name portion of filename).
    msecs%(msecs)dMillisecond portion of the time when the LogRecord was created.
    msgYou shouldn’t need to format this yourself.The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object (see Using arbitrary objects as messages).
    name%(name)sName of the logger used to log the call.
    pathname%(pathname)sFull pathname of the source file where the logging call was issued (if available).
    process%(process)dProcess ID (if available).
    processName%(processName)sProcess name (if available).
    relativeCreated%(relativeCreated)dTime in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
    stack_infoYou shouldn’t need to format this yourself. Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.
    thread%(thread)dThread ID (if available).
    threadName%(threadName)sThread name (if available).

    三:使用

    3.1 编码方式(个人推荐使用这种)

    封装一个日志类。

    import os
    import sys
    import logging
    from logging.handlers import RotatingFileHandler
    import datetime
    
    current_path = os.path.dirname(__file__)
    log_path = os.path.join(current_path, f'../logs/app-{datetime.date.today()}.log')
    
    
    class LogUtils:
        def __init__(self):
            self.log_path = log_path
            self.logger = logging.getLogger(__name__)
            self.logger.setLevel(logging.DEBUG)
    
            formatter = logging.Formatter(
                fmt='%(asctime)s %(levelname)s %(thread)d --- [%(threadName)s] %(filename)s %(funcName)s:%(lineno)d:%(message)s')
    
            console_handler = logging.StreamHandler()
            console_handler.setFormatter(formatter)
    
    		# RotatingFileHandler 根据日志文件大小自动生成日志文件
            # 单个文件最大3k,最多保存3份文件(除了当前写入的文件外),实际情况这个值要设的很大sys.maxsize,防止覆盖 超过则循环式覆盖
            rotating_file_handler = RotatingFileHandler(log_path, maxBytes=1024 * 3, backupCount=3, encoding='utf-8')
    
    		# TimedRotatingFileHandler 往文件里写入: 根据时间间隔自动生成日志 文件
            # interval是时间间隔,
            # backupCount是备份文件的个数,如果超过这个个数,就会自动删除,
            # when是间隔的时间单位,单位有以下几种:S 秒, M 分, H 小时, D 天, W 每星期(interval==0时代表星期一, midnight 每天凌晨
            timed_rotating_file_handler = handlers.TimedRotatingFileHandler(filename=filename, when='D', backupCount=3, encoding='utf-8')
    
      
            rotating_file_handler.setFormatter(formatter)
    
            file_handler = logging.FileHandler(log_path, encoding='utf-8')
            file_handler.setFormatter(formatter)
            self.logger.addHandler(console_handler)
            # self.logger.addHandler(file_handler)
            self.logger.addHandler(rotating_file_handler)
    
        def get_logger(self):
            return self.logger
    
    
    logger = LogUtils().get_logger()
    
    

    日志测试

    from common.log_utils import logger
    
    if __name__ == '__main__':
        for i in range(40):
            logger.info(f" {i} info测试info测试info测试info测试info测试info测试info测试info测试info测试info测试info测试info测试info测试info测试.")
    

    注意:这里和我的认知不太一样,这里先从最后一个日志文件开始写,即先从2号开始写,然后是1号,最后是没有标号的文件。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3.2 配置文件方式 fileConfig

    logging.conf

    [loggers]
    # 配置logger信息。必须包含一个名字叫做root的logger,当使用无参函数logging.getLogger()时,默认返回root这个logger,
    # 其他自定义logger可以通过 logging.getLogger("fileAndConsole") 方式进行调用
    keys=root,fileAndConsole
    
    [handlers]
    # 定义声明handlers信息。
    keys=fileHandler,consoleHandler
    
    [formatters]
    # 设置日志格式
    keys=simpleFormatter
    
    [logger_root]
    # 对loggers中声明的logger进行逐个配置,且要一一对应,在所有的logger中,必须制定level和handlers这两个选项,
    # 对于非roothandler,还需要添加一些额外的option,其中qualname表示它在logger层级中的名字,在应用代码中通过这个名字制定所使用的handler,
    # 即 logging.getLogger("fileAndConsole"),handlers可以指定多个,中间用逗号隔开,比如handlers=fileHandler,consoleHandler,同时制定使用控制台和文件输出日志
    level=DEBUG
    handlers=consoleHandler,fileHandler
    
    [logger_fileAndConsole]
    level=DEBUG
    handlers=fileHandler,consoleHandler
    qualname=fileAndConsole
    propagate=0
    
    [handler_consoleHandler]
    # 在handler中,必须指定class和args这两个option,常用的class包括
    # StreamHandler(仅将日志输出到控制台)、FileHandler(将日志信息输出保存到文件)、
    # RotaRotatingFileHandler(将日志输出保存到文件中,并设置单个日志wenj文件的大小和日志文件个数),
    # args表示传递给class所指定的handler类初始化方法参数,它必须是一个元组(tuple)的形式,即便只有一个参数值也需要是一个元组的形式;
    # 里面指定输出路径,比如输出的文件名称等。level与logger中的level一样,而formatter指定的是该处理器所使用的格式器,
    # 这里指定的格式器名称必须出现在formatters这个section中,且在配置文件中必须要有这个formatter的section定义;
    # 如果不指定formatter则该handler将会以消息本身作为日志消息进行记录,而不添加额外的时间、日志器名称等信息;
    class=StreamHandler
    args=(sys.stdout,)
    level=DEBUG
    formatter=simpleFormatter
    
    [handler_fileHandler]
    class=FileHandler
    args=('test.log', 'a')
    level=DEBUG
    formatter=simpleFormatter
    
    [formatter_simpleFormatter]
    format=%(asctime)s %(levelname)s %(thread)d --- [%(threadName)s] %(filename)s %(funcName)s:%(lineno)d:%(message)s
    datefmt=%Y-%m-%d %H:%M:%S
    
    import logging.config
    
    logging.config.fileConfig('./config/logging.conf')
    logger = logging.getLogger()
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warn message')
    logger.error('error message')
    logger.critical('critical message')
    

    3.3 配置字典方式 dictConfig

    LOGGING_CONFIG = {
        "version": 1,
        "formatters": {
            "default": {
                'format': '%(asctime)s %(levelname)s %(thread)d --- [%(threadName)s] %(filename)s %(funcName)s:%(lineno)d:%(message)s',
            }
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "level": logging.DEBUG,
                "formatter": "default"
            },
            "file": {
                "class": "logging.FileHandler",
                "level": logging.DEBUG,
                "filename": "./log.txt",
                "formatter": "default",
            }
        },
        "root": {
            "handlers": ["console", "file"],
            "level": "DEBUG"
        },
    }
    
    logging.config.dictConfig(LOGGING_CONFIG)
    logger = logging.getLogger()
    
    logger.debug('debug message')
    logger.info('info message')
    logger.warning('warn message')
    logger.error('error message')
    logger.critical('critical message')
    
  • 相关阅读:
    ArcGIS:如何对要素类进行查询要素属性、更改符号、标记?
    栩栩如生,音色克隆,Bert-vits2文字转语音打造鬼畜视频实践(Python3.10)
    Java 入门练习(36 - 40)
    第1讲 Android Camera Native Framework 课程介绍
    Mybatis-Plus自动填充失效原因和解决方案
    vsftpd使用
    中位数的题
    Linux基础篇(6)---》常用命令大全(网络命令+关机重启命令)
    双势阱模型
    js基础总结
  • 原文地址:https://blog.csdn.net/vbirdbest/article/details/127040827