【python 内置模块】logging

2024-01-20 00:00:00

目录:

logging 模块介绍

logging 模块的架构基于四个核心组件,它们协同工作以完成日志的记录与输出。

工作流程是:开发者调用 Logger 方法 → Logger 根据自身级别判断是否处理该日志 → 日志记录通过可选的 Filter → 被传递给所有附加的 Handler → 每个 Handler 根据自身级别和 Formatter 的格式,将日志输出到其目标位置。

Logger(日志器)

每个Logger对象都有一个名称,通常与模块名(__name__)相关联,开发者通过调用Logger的方法(如 logger.debug()、logger.info())来产生日志记录。

Handler(处理器)

将Logger产生的日志记录发送到指定的目的地。可以将同一条日志同时输出到控制台和文件等不同位置。

  • StreamHandler:输出到控制台;
  • FileHandler:输出到文件;
  • RotatingFileHandler:按文件大小自动轮转日志文件,防止单个文件过大;
  • TimedRotatingFileHandler:按时间间隔自动轮转日志文件;

Formatter(格式化器)

决定了日志记录的最终输出格式。

可以指定日志信息中包含哪些内容,如时间戳、日志级别、模块名、行号以及具体的消息等。开发者可以通过格式化字符串自定义输出样式。

Filter(过滤器)

可以基于Logger名称、日志级别或其他自定义条件来决定是否让某条日志记录通过。

日志级别

  • DEBUG:最详细的级别,用于记录调试信息,通常在开发阶段使用;
  • INFO:用于确认程序按预期运行,记录一般性信息;
  • WARNING:表示发生了意外情况或潜在问题,但程序仍能继续运行;
  • ERROR:记录程序运行中的错误,导致某些功能无法正常工作;
  • CRITICAL:最高级别,记录严重的错误,可能导致程序崩溃;

INFO 级别用的最多。

简单使用

对于简单的脚本,可以使用 logging.basicConfig() 进行一次性全局配置。这个函数会为根(root)Logger设置一个默认的Handler(通常是StreamHandler)。

logging.basicConfig() 只在第一次调用时生效。通常应在程序入口(如主函数开始处)进行配置。

import logging

# 基础配置:设置级别和格式,输出到控制台
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(levelname)s - %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S')

# 使用根Logger记录日志
logging.debug('这是一条调试信息')
logging.info('这是一条普通信息')
logging.warning('这是一条警告信息')

format参数支持丰富的占位符,例如:

  • %(asctime)s 表示时间
  • %(levelname)s 表示级别名称
  • %(message)s 表示消息内容
  • %(filename)s 表示文件名
  • %(lineno)d 表示行号
  • %(name)s 表示日志器名称,也就是 logging.getLogger() 中传入的参数

项目使用

在正式的应用程序或项目中,更推荐创建和配置自定义的 Logger 对象,这样可以获得更精细的控制,并避免模块间的日志冲突。

# logger.py
import logging

def setup_logger(name):
    # 1. 创建 Logger 对象,通常以模块名命名
    logger = logging.getLogger(name)
    # 设置 Logger 的捕获级别
    logger.setLevel(logging.DEBUG)  

    # 可选:防止日志向上传递给父 Logger,避免重复输出
    logger.propagate = False

    # 2. 创建 Handler:一个输出到控制台,一个输出到文件
    console_handler = logging.StreamHandler()
    file_handler = logging.FileHandler('app.log', encoding='utf-8')

    # 3. 为每个 Handler 设置独立的输出级别
    # 控制台只显示 INFO 及以上
    console_handler.setLevel(logging.INFO)
    # 文件记录所有 DEBUG 及以上的日志    
    file_handler.setLevel(logging.DEBUG)      

    # 4. 创建 Formatter 并绑定到 Handler
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    console_handler.setFormatter(formatter)
    file_handler.setFormatter(formatter)

    # 5. 将 Handler 添加到 Logger
    logger.addHandler(console_handler)
    logger.addHandler(file_handler)

    return logger

在其它文件中使用日志:

# sample.py
from logger import setup_logger

logger = setup_logger(__name__)

def do_something():
    logger.info('开始搞点事情...')

按文件大小轮转日志

对于长期运行的服务,日志文件会不断增长。logging.handlers 提供了 RotatingFileHandler 来自动管理日志文件大小,防止磁盘被占满。

import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger(__name__)

# 创建按大小轮转的 Handler,每个文件最大 1MB,保留 3 个备份
file_handler = RotatingFileHandler('app.log', maxBytes=1024*1024, backupCount=3)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)

logger.addHandler(file_handler)

按时间轮转日志

对于长期运行的服务,日志文件会不断增长。logging.handlers 提供了 TimedRotatingFileHandler 来按时间归档,防止磁盘被占满。以下是按天轮转日志示例:

import logging
from logging.handlers import TimedRotatingFileHandler

logger = logging.getLogger(__name__)

# 关键参数说明:
# filename: 日志文件的基础名称(前缀)。
# when: 轮转时间单位。'D'代表天,其他选项包括:'S'(秒), 'M'(分), 'H'(小时), 'W0'-'W6'(周), 'midnight'(每天零点)
# interval: 轮转间隔数。when='D', interval=1 表示每天轮转一次。
# backupCount: 保留的历史日志文件数量。设为 7 表示保留最近 7 天的日志,更早的自动删除
# encoding: 确保日志文件能正确记录中文等非ASCII字符
file_handler = TimedRotatingFileHandler(
    filename='app.log',
    when='D',
    interval=1,
    backupCount=7,
    encoding='utf-8'
)
file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(funcName)s - Line %(lineno)d - %(message)s')
file_handler.setFormatter(file_formatter)

logger.addHandler(file_handler)

返回首页

本文总阅读量  次
皖ICP备17026209号-3
总访问量: 
总访客量: