跳转至

Python日志记录(Logging)简介与应用

学习目标

  1. 理解日志记录的作用及其在程序开发中的重要性。
  2. 掌握Python logging 模块的基本用法。
  3. 学会通过示例配置日志级别、格式,并将日志存储到文件中。
  4. 在工程化项目中应用日志记录,追踪程序运行状态。

日志记录概述

日志(Logging)是程序运行时记录关键信息的一种方式,例如操作成功、错误发生或调试信息。它在开发和维护中非常重要,因为:

  • 调试:帮助找到代码中的问题。
  • 监控:记录程序的运行状态。
  • 审计:追踪用户或系统的行为。

Python的logging模块是一个内置工具,提供灵活的日志记录功能,比简单的print语句更强大。

核心概念

  1. 日志级别:表示日志的重要性,常见级别从低到高:
    • DEBUG:调试信息(最低)。
    • INFO:一般信息。
    • WARNING:警告,可能有问题。
    • ERROR:错误,已影响程序。
    • CRITICAL:严重错误(最高)。
  2. 日志处理器(Handler):决定日志输出到哪里(如控制台或文件)。
  3. 日志格式(Formatter):定义日志的显示样式(如时间、级别、消息)。

示例1:基础日志记录

目标

通过简单示例展示如何记录日志到控制台。

代码

import logging

# 配置基本的日志设置
logging.basicConfig(level=logging.INFO)

# 获取日志记录器
logger = logging.getLogger("Example1")

# 记录不同级别的日志
logger.debug("这是调试信息,通常用于开发")
logger.info("程序运行正常")
logger.warning("注意,可能有小问题")
logger.error("发生错误")
logger.critical("严重错误,程序可能崩溃")

运行结果

2025-04-01 10:00:00,123 INFO Example1: 程序运行正常
2025-04-01 10:00:00,124 WARNING Example1: 注意,可能有小问题
2025-04-01 10:00:00,125 ERROR Example1: 发生错误
2025-04-01 10:00:00,126 CRITICAL Example1: 严重错误,程序可能崩溃

分析

  • basicConfig(level=logging.INFO)设置最低记录级别为INFO,因此DEBUG信息未显示。
  • 日志默认输出到控制台,格式为时间 级别 名称: 消息

示例2:自定义日志格式

目标

自定义日志输出格式,添加时间和级别。

代码

import logging

# 配置日志格式
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

# 获取日志记录器
logger = logging.getLogger("Example2")

# 记录日志
logger.debug("调试模式已开启")
logger.info("正在处理数据")
logger.error("数据处理失败")

运行结果

2025-04-01 10:00:00,123 - DEBUG - 调试模式已开启
2025-04-01 10:00:00,124 - INFO - 正在处理数据
2025-04-01 10:00:00,125 - ERROR - 数据处理失败

分析

  • format参数使用占位符:
    • %(asctime)s:记录时间。
    • %(levelname)s:日志级别。
    • %(message)s:日志消息。
  • 级别设为DEBUG,所有日志都显示。

示例3:将日志存储到文件

目标

将日志保存到文件中,便于后续查看。

代码

import logging

# 配置日志,输出到文件
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='app.log',  # 日志文件路径
    filemode='a'         # 'a'表示追加,'w'表示覆盖
)

# 获取日志记录器
logger = logging.getLogger("Example3")

# 记录日志
logger.info("程序启动")
logger.warning("内存使用率较高")
logger.error("无法连接数据库")

运行结果

  • 控制台无输出,日志写入app.log文件:
    2025-04-01 10:00:00,123 - INFO - 程序启动
    2025-04-01 10:00:00,124 - WARNING - 内存使用率较高
    2025-04-01 10:00:00,125 - ERROR - 无法连接数据库
    

分析

  • filename指定日志文件路径。
  • filemode='a'确保日志追加写入,不覆盖之前的内容。

示例4:同时输出到控制台和文件

目标

将日志同时记录到控制台和文件中。

代码

import logging

# 创建日志记录器
logger = logging.getLogger("Example4")
logger.setLevel(logging.DEBUG)  # 设置记录器级别

# 创建控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)  # 控制台显示INFO及以上级别

# 创建文件处理器
file_handler = logging.FileHandler('app.log', mode='a')
file_handler.setLevel(logging.DEBUG)  # 文件记录DEBUG及以上级别

# 定义日志格式
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

# 为处理器设置格式
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

# 将处理器添加到记录器
logger.addHandler(console_handler)
logger.addHandler(file_handler)

# 记录日志
logger.debug("调试信息,仅写入文件")
logger.info("程序运行正常")
logger.error("发生错误")

运行结果

  • 控制台输出
    2025-04-01 10:00:00,123 - INFO - 程序运行正常
    2025-04-01 10:00:00,124 - ERROR - 发生错误
    
  • app.log文件内容
    2025-04-01 10:00:00,123 - DEBUG - 调试信息,仅写入文件
    2025-04-01 10:00:00,124 - INFO - 程序运行正常
    2025-04-01 10:00:00,125 - ERROR - 发生错误
    

分析

  • 使用Handler分别控制输出目标:
    • StreamHandler:输出到控制台。
    • FileHandler:输出到文件。
  • 不同处理器可设置不同级别,灵活性更高。

代码实现

整体结构

logging_lesson/
├── logs/
│   └── app.log      # 日志文件
├── utils/
│   └── logger.py    # 日志配置模块
├── main.py          # 主程序入口
└── requirements.txt # 依赖文件(本例无需额外依赖)

日志配置模块 (utils/logger.py)

import logging
import os

def setup_logger(name, log_file='logs/app.log'):
    # 确保日志目录存在
    os.makedirs(os.path.dirname(log_file), exist_ok=True)

    # 创建日志记录器
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)  # 设置最低级别

    # 创建控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)

    # 创建文件处理器
    file_handler = logging.FileHandler(log_file, mode='a')
    file_handler.setLevel(logging.DEBUG)

    # 定义日志格式
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')

    # 设置处理器格式
    console_handler.setFormatter(formatter)
    file_handler.setFormatter(formatter)

    # 添加处理器(避免重复添加)
    if not logger.handlers:
        logger.addHandler(console_handler)
        logger.addHandler(file_handler)

    return logger

主程序 (main.py)

from utils.logger import setup_logger

# 初始化日志记录器
logger = setup_logger("MainApp")

def process_data(data):
    logger.debug(f"开始处理数据: {data}")
    if not data:
        logger.error("数据为空,无法处理")
        return None
    logger.info("数据处理完成")
    return data.upper()

def main():
    logger.info("程序启动")
    result = process_data("hello")
    if result:
        logger.info(f"处理结果: {result}")
    else:
        logger.warning("处理失败")
    logger.info("程序结束")

if __name__ == "__main__":
    main()

运行结果

  • 控制台输出
    2025-04-01 10:00:00,123 - INFO - MainApp - 程序启动
    2025-04-01 10:00:00,124 - INFO - MainApp - 数据处理完成
    2025-04-01 10:00:00,125 - INFO - MainApp - 处理结果: HELLO
    2025-04-01 10:00:00,126 - INFO - MainApp - 程序结束
    
  • logs/app.log 文件内容
    2025-04-01 10:00:00,123 - INFO - MainApp - 程序启动
    2025-04-01 10:00:00,124 - DEBUG - MainApp - 开始处理数据: hello
    2025-04-01 10:00:00,125 - INFO - MainApp - 数据处理完成
    2025-04-01 10:00:00,126 - INFO - MainApp - 处理结果: HELLO
    2025-04-01 10:00:00,127 - INFO - MainApp - 程序结束
    

总结

本课通过示例讲解了Python logging 模块的使用:

  • 基础:使用basicConfig快速配置日志。
  • 自定义:设置格式、级别和输出目标。
  • 存储:将日志保存到文件,同时支持控制台输出。
  • 工程化:封装日志配置为模块,便于复用。

应用场景

  • 在QA系统中,记录数据库连接、检索结果等状态。
  • 调试时使用DEBUG级别,生产环境调整为INFOERROR