【Python】调试模块logging详解及python代码示例

1. logging基本使用

logging日志级别:

级别数值使用场景示例生产环境建议
DEBUG10变量跟踪、算法中间状态关闭
INFO20服务启动、关键业务流程节点保留
WARNING30低磁盘空间、非预期参数但可处理保留
ERROR40数据库连接失败、文件解析异常保留
CRITICAL50系统崩溃、核心服务不可用保留

默认日志级别warning

使用logging向控制台输出日志代码示例:

import logging

# 默认日志输出级别warning
# 指定输出级别basicConfig

logging.basicConfig(level=logging.DEBUG)

# 能保证logging输出顺序一致,但是能保证logging与print输出顺序一致
# 可能会出现先输出logging,再输出print的情况, 内部日志输出机制不是同步的, 异步写入, 支持高并发

print("this is print log")

logging.debug("This is Debug log")
logging.info("This is info log")
logging.warning("This is warning log")
logging.error("This is error log")
logging.critical("This is citical log")

logging将日志输出到文件:

import logging

# 默认日志输出级别warning
# 指定输出日志文件、日志记录级别 basicConfig
# 如果没有会新建demo.log文件,若有则会在文件后追加log日志
# filemode = "w"先清空再写入, "a"是追加写入, 默认是追加写入

logging.basicConfig(filename='demo.log',  filemode="w", encoding="utf-8", level=logging.DEBUG)

logging.debug("This is Debug log")
logging.info("This is info log")
logging.warning("This is warning log")
logging.error("This is error log")
logging.critical("This is citical log")

logging输出变量:

import logging

# 向日志输出变量
logging.basicConfig(level=logging.DEBUG)

name = "张三"
age = 18

logging.debug("This is Debug log")
logging.debug("姓名 %s, 年龄 %d", name, age)
logging.debug("姓名 %s, 年龄 %d" % (name, age))
logging.debug("姓名 {}, 年龄{}".format(name, age))
logging.debug(f"姓名 {name}, 年龄{age}")

# 输出
# DEBUG:root:This is Debug log
# DEBUG:root:姓名 张三, 年龄 18
# DEBUG:root:姓名 张三, 年龄 18
# DEBUG:root:姓名 张三, 年龄18
# DEBUG:root:姓名 张三, 年龄18

输出日期:

import logging

# 输出格式和添加一些公共变量, 时间,日志级别,所在行数,信息
# datafmt 设置时间格式

logging.basicConfig(format="%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s",
                    datefmt="%Y-%m-%d %H:%M:%S",
                    level=logging.DEBUG)

name = "张三"
age = 18
logging.debug("姓名 %s, 年龄 %d", name, age)
# 输出:
# 2025-03-13 08:10:33 | DEBUG | mylog.py:11 | 姓名 张三, 年龄 18

2. logging的高级应用

logging模块采用了模块化设计,主要包含四种组件:

  • Loggers:记录器,提供应用程序代码能直接使用的接口
  • Handlers:处理器,将记录器产生的日志发送至目的地
  • Filters:过滤器,提供更好的粒度控制,决定哪些日志会被输出
  • Formatters:格式化器,设置日志内容的组成结构和消息字段

一个记录器可以对应多个处理器
在这里插入图片描述

loggers记录器:

  1. 提供应用程序的调用接口
    logger = logging.getLogger(__name__)

  2. 决定日志记录的级别
    logger.setLevel()

  3. 将日志内容传递到相关联的handlers中:
    logger.addHandler() 和 logger.removeHandler()

只要 __name__不变,logger就是单例的

Handlers处理器:

他们将日志分发到不同的目的地。可以是文件、标准输出、邮件、或者socket、http等协议发送到任何地方

StreamHandler:

  • 标准输出 stdout 分发器
  • 创建方法:sh=logging.StreamHandler(stream=None)

FileHandler:

  • 将日志保存到磁盘文件的处理器
  • 创建方法: fh = logging.FileHandler(filename, mode=“a”, encoding=None, delay=False)
  • setFormatter() : 设置当前 handler 对象使用的消息格式

其它Handdlers处理器:

FileHandler: 只会往一个文件中写,需要人为备份
RotatingFileHandler: 按照文件大小分别写入日志
TimedRotatingFileHandler:按照时间写入日志
在这里插入图片描述

Formatters格式:

  • Formatters对象用来最终设置日志信息的顺序、结构和内容

  • 其构造方法为:ft = logging.Formatter.__init__(fmt=None, datefmt=None, style=’ %')

  • datefmt 默认是 %Y-%m-%d %H:%M:%S样式的

  • style 参数默认为百分符 %, 这表示 %(<dictionary key>)s 格式的字符串

在这里插入图片描述

Python代码示例:

import logging

# 记录器
logger = logging.getLogger('applog')
logger.setLevel(logging.DEBUG) 

# 处理器handler
# 向终端输出
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.INFO)

# 向文件输出,没有设置日志级别,将使用logger的级别
fileHnadler = logging.FileHandler(filename="addDemo.log")
fileHnadler.setLevel(logging.INFO)

# Formatter格式
formatter = logging.Formatter("%(asctime)s|%(levelname)8s|%(filename)s:%(lineno)4s|%(message)s")

# 给处理器设置格式
consoleHandler.setFormatter(formatter)
fileHnadler.setFormatter(formatter)

# 记录器设置处理器,会向控制台和 文件同时写入日志
logger.addHandler(consoleHandler)
logger.addHandler(fileHnadler)

# 定义一个过滤器
flt = logging.Filter("cn.cccb") # logger现在的名字是 app.log, 不满足以cn.cccb开头,所以没有日志输出

# 关联过滤器
# logger.addFilter(flt)     # 记录器关联过滤器
fileHnadler.addFilter(flt)  # 处理器关联过滤器

# 打印日志代码
logger.debug("This is debug log")
logger.info("This is info log")
logger.warning("This is warning log")
logger.error("This is error log")
logger.critical("This is critical log")

使用配置文件的形式:

测试代码:

import logging
import logging.config

# 配置文件方式来处理日志
# 记录器

logging.config.fileConfig('logging.conf')

rootLogger = logging.getLogger()
rootLogger.debug("this is root Logger, debug")

logger = logging.getLogger('applog')
logger.debug("This is applog Logger , debug")


a = 'abc'
try:
    int(a)
except Exception as e:
    logger.exception(e)     # 将报错输出到日志

# 1. 代码形式
# 2. 配置文件形式
# 3. 字典形式

logging.conf :

[loggers]
keys = root,applog    

[handlers]
keys = fileHandler, consoleHandler

[formatters]
keys = simpleFormatter

[logger_root]
level = DEBUG
handlers = consoleHandler

[logger_applog]
level = DEBUG
handlers = fileHandler,consoleHandler
qualname = applog       
propagate = 0           

[handler_consoleHandler]
class = StreamHandler
args = (sys.stdout,)
level = DEBUG
formatter = simpleFormatter

[handler_fileHandler]
class = logging.handlers.TimedRotatingFileHandler
# 参数说明:filename, when, interval, backupCount
args = ('applog.log', 'midnight',1,0)  
level = DEBUG
formatter = simpleFormatter

[formatter_simpleFormatter]
format = %(asctime)s|%(levelname)8s|%(filename)s:%(lineno)4d|%(message)s
datefmt = %Y-%m-%d %H:%M:%S

本文参考: https://www.bilibili.com/video/BV1sK4y1x7e1/?spm_id_from=333.1387.favlist.content.click&vd_source=cf0b4c9c919d381324e8f3466e714d7a

3. logging初始化封装示例

import os
import logging

# log 日志相关设置
class LoggerConfig(Enum):
    LOG_NAME = "WPF"                            
    LOG_DIR = "logs"
    LOGGER_FORMATTER = "%(asctime)s|%(levelname)8s|%(filename)s:%(lineno)4s|%(message)s"
    LOGGER_LEVEL = logging.DEBUG            # logger日志级别
    LOGGER_MODE = 0                         # 0:控制台和文件日志输出  1:控制台日志输出  2: 文件日志输出

def setup_logging(
        name = LoggerConfig.LOG_NAME.value,
        log_dir = LoggerConfig.LOG_DIR.value,
        logger_formatter = LoggerConfig.LOGGER_FORMATTER.value,
        level = LoggerConfig.LOGGER_LEVEL.value,
        mode = LoggerConfig.LOGGER_MODE.value
    ):
    """
    初始化日志
    Args:
        name: log 名称
        log_dir: 日志存放目录
        logger_formatter: 日志格式
        level: 日志级别
        mode: 0、1、2   0:控制台和文件日志输出  1:控制台日志输出  2: 文件日志输出
    """
    # 如果日志目录不存在则创建
    try:
        os.makedirs(log_dir, exist_ok=True)
    except Exception as e:
        raise RuntimeError(f"创建日志目录失败: {log_dir}") from e
    
    
    # 记录器
    logger = logging.getLogger(name)
    logger.setLevel(level)

    # 格式    
    formatter = logging.Formatter(logger_formatter)
    
    # 终端输出处理器
    consoleHandler = logging.StreamHandler()
    consoleHandler.setLevel(level)
    consoleHandler.setFormatter(formatter)
    
    # 文件输出处理器
    log_file = os.path.join(log_dir, f"{name}.log")
    fileHandle = logging.FileHandler(log_file)
    fileHandle.setLevel(level)
    fileHandle.setFormatter(formatter)
    
    # 模式
    if mode == 0:
        logger.addHandler(consoleHandler)
        logger.addHandler(fileHandle)
    
    elif mode ==1:
        logger.addHandler(consoleHandler)
        
    elif mode==2:
        logger.addHandler(fileHandle)
        
    else:
        raise ValueError(f"无效的模式参数: {mode},可选值 0/1/2")
    
    return logger


logger = setup_logging()

if __name__ == "__main__":
    pass


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值