【python】python进阶——logging日志模块

目录

引言

一、logging对比print

二、基本使用方法

[三、logging 模块的核心组件](#三、logging 模块的核心组件)

[3.1 Logger (记录器)](#3.1 Logger (记录器))

[3.2 Handler (处理器)](#3.2 Handler (处理器))

[3.3 Formatter (格式化器)](#3.3 Formatter (格式化器))

[3.4 Filter (过滤器)](#3.4 Filter (过滤器))

[3.5 核心组件快速使用示例](#3.5 核心组件快速使用示例)

四、高级用法与最佳实践

1、配置分离:将日志配置独立出来

[2、RotatingFileHandler 分割日志文件](#2、RotatingFileHandler 分割日志文件)

3、捕获异常信息

[4、在多模块项目中使用 name](#4、在多模块项目中使用 name)

5、避免重复日志

总结

参考


引言

在软件开发中,日志(Logging)是不可或缺的工具。它帮助我们追踪程序执行流程、诊断错误、监控系统状态,是调试、运维和分析用户行为的关键。Python 内置的 logging 模块功能强大且灵活,远超简单的**print** 语句。


一、logging对比print

你可能习惯用 print() 输出信息,但 logging 模块提供了 print 无法比拟的优势:

  1. 日志级别(Levels) :支持 DEBUG, INFO, WARNING, ERROR, CRITICAL 等级别,可以方便地控制不同环境(开发、测试、生产)输出的信息量。

  2. 灵活的输出目标(Handlers) :日志可以同时输出到控制台、文件、网络、邮件、数据库等,而 print 只能输出到标准输出。

  3. 丰富的格式化(Formatters):可以自定义日志的输出格式,包含时间、模块名、行号、日志级别等信息。

  4. 性能 :在生产环境中,可以将日志级别设为 WARNING,此时 debug() 调用几乎不消耗性能(因为消息不会被格式化),而 print 语句即使注释掉也需要手动操作。

  5. 结构化与可维护性logging 提供了清晰的架构,易于配置和管理,适合大型项目。


二、基本使用方法

2.1 导入 logging 模块

python 复制代码
import logging

2.2 日志级别介绍

日志级别用于控制日志的详细程度。**logging**模块提供了以下几种日志级别:

级别 数值 说明
CRITICAL 50 致命,严重错误,程序可能无法继续运行
ERROR 40 错误,但程序仍可运行
WARNING 30 警告,表示潜在的问题,但程序仍能正常运行。默认级别)
INFO 20 提示,程序正常运行时的信息
DEBUG 10 调试,详细的调试信息,通常用于开发阶段
NOTSET 0 继承,继承父记录器的级别

注意 :默认日志级别是 WARNING,即低于 WARNING 的日志不会被输出。

需要设置日志显示的最低显示级别。如显示所有日志,设置为最低级别**DEBUG:**

python 复制代码
logging.basicConfig(level=logging.DEBUG)

2.3 简单使用示例

快速使用日志的完整功能示例:

python 复制代码
import logging
logging.basicConfig(level=logging.INFO)

logging.debug("这是一条调试信息")
logging.info("这是一条普通信息")
logging.warning("这是一条警告信息")
logging.error("这是一条错误信息")
logging.critical("这是一条严重错误信息")

运行结果:

三、logging 模块的核心组件

logging 模块基于一个经典的 生产者-过滤器-处理器 模型,主要由四个核心对象构成:

说明 示例
logging.Logger 记录器,用于发出日志消息 logger = logging.getLogger("my_logger")
logging.Handler 处理器,决定日志输出位置(如文件、控制台等) handler = logging.FileHandler("app.log")
logging.Formatter 格式化器,控制日志输出的格式 formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
logging.Filter 过滤器,用于更精细地控制日志记录 filter = logging.Filter("module.name")

3.1 Logger (记录器)

  • 角色 :应用程序的接口。你通过 Logger 对象调用 debug(), info(), warning(), error(), critical() 方法来记录日志。

  • 关键属性

    • 名称(Name) :通常使用 logging.getLogger(__name__) 创建,__name__ 是模块的全名(如 myapp.module),这有助于组织日志层次结构。

    • 级别(Level)Logger 有一个日志级别。只有级别大于或等于此级别的日志记录才会被处理。如果 Logger 本身没有设置级别,它会向上传递到父 Logger(最终到根 Logger)。

  • 层级结构Logger 按名称形成树状结构。myappmyapp.module 的父 Logger。日志消息会沿着这个层级向上传播,除非设置了 propagate=False

3.2 Handler (处理器)

  • 角色 :决定日志消息的最终去向 。一个 Logger 可以有多个 Handler

  • 常见 Handler

    • StreamHandler :输出到流(如 sys.stdout, sys.stderr)。

    • FileHandler:输出到文件。

    • RotatingFileHandler:输出到文件,并在文件达到一定大小时轮转。

    • TimedRotatingFileHandler:按时间(如每天)轮转日志文件。

    • SMTPHandler:通过邮件发送日志。

    • SocketHandler / DatagramHandler:通过网络发送日志。

处理器 说明
StreamHandler 输出到控制台(sys.stdout / sys.stderr)
FileHandler 输出到文件(文本)
RotatingFileHandler 按大小轮转日志文件
TimedRotatingFileHandler 按时间轮转日志文件
SMTPHandler 通过邮件发送日志
SocketHandler / DatagramHandler 通过网络发送日志
NullHandler 空处理器,用于避免无 handler 时的警告
  • 关键属性

    • 级别(Level)Handler 也有自己的级别。即使 Logger 接受了一条日志,Handler 也会根据自己的级别再次过滤。例如,Logger 级别是 DEBUGHandler 级别是 INFO,那么 DEBUG 级别的日志不会被这个 Handler 处理。

    • Formatter :关联一个 Formatter 来格式化日志消息。

3.3 Formatter (格式化器)

  • 角色 :定义日志消息的最终输出格式

  • 格式 :使用类似 %(asctime)s - %(name)s - %(levelname)s - %(message)s 的字符串。

  • 可以为不同的 Handler 设置不同的 Formatter。例如,文件日志包含详细信息(时间、行号),而控制台日志只显示简洁信息。

Formatter 常用格式字段如下:

字段 说明 示例输出
%(asctime)s 日志创建时间 2023-01-01 12:00:00,123
%(levelname)s 日志级别名称 INFO
%(message)s 日志消息内容 程序启动成功
%(name)s 记录器名称 my_logger
%(filename)s 生成日志的文件名 app.py
%(lineno)d 生成日志的行号 42
%(funcName)s 生成日志的函数名 main
%(pathname)s 生成源文件的完整路径
%(module)s 生成模块名(文件名去掉 .py
%(process)d 生成进程ID
%(thread)d 生成线程 ID

3.4 Filter (过滤器)

  • 角色 :提供更精细的日志过滤机制,可以基于 Logger 名称、日志级别或其他属性进行过滤。

  • 使用场景 :相对较少直接使用,LoggerHandler 的级别通常足够。但可以用于实现复杂逻辑,比如只记录特定用户的日志。


3.5 核心组件快速使用示例

python 复制代码
import logging

# 1. 获取一个 Logger 实例(通常使用模块名)
logger = logging.getLogger(__name__)

# 2. 设置 Logger 级别
logger.setLevel(logging.DEBUG)

# 3. 创建 Handler (例如,输出到控制台)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO) # Handler 级别

# 4. 创建 Formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)

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

# 6. 记录日志
logger.debug("调试信息")
logger.info("普通信息")
logger.warning("警告信息")
logger.error("错误信息")
logger.critical("严重错误")

运行结果:


四、高级用法与最佳实践

1、配置分离:将日志配置独立出来

将配置放在单独的文件中,是大型项目的标准做法。推荐使用**dictConfig**。

python 复制代码
# logging_config.py
import logging
from logging.config import dictConfig
​
LOGGING_CONFIG = {
    "version": 1,
    "disable_existing_loggers": False,  # 避免禁用第三方库日志
    "formatters": {
        "detailed": {
            "format": "%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s"
        },
        "simple": {
            "format": "%(name)s - %(levelname)s - %(message)s"
        }
    },
    "handlers": {
        "file": {
            "class": "logging.handlers.RotatingFileHandler", # 轮转文件
            "level": "DEBUG",
            "formatter": "detailed",
            "filename": "app.log",
            "maxBytes": 10485760,  # 10MB
            "backupCount": 5,      # 保留 5 个备份
            "encoding": "utf-8"
        },
        "console": {
            "class": "logging.StreamHandler",
            "level": "INFO",
            "formatter": "simple"
        }
    },
    "loggers": {
        "myapp": {  # 为你的应用定义 logger
            "level": "DEBUG",
            "handlers": ["file", "console"],
            "propagate": False
        }
    }
}
​
dictConfig(LOGGING_CONFIG)
logger = logging.getLogger("myapp") # 创建全局 logger 实例

在其他模块中使用:

python 复制代码
# main.py
from logging_config import logger
​
logger.info("应用启动")

2、RotatingFileHandler 分割日志文件

FileHandler 会无限增长文件。使用 RotatingFileHandlerTimedRotatingFileHandler 可以自动管理日志文件大小和数量。

3、捕获异常信息

python 复制代码
try:
    result = 1 / 0
except Exception as e:
    logger.error("发生异常", exc_info=True) # exc_info=True 会自动记录 traceback
    # 或者使用
    # logger.exception("发生异常") # 等价于 logger.error(..., exc_info=True)

4、在多模块项目中使用 name

python 复制代码
# myapp/utils.py
import logging
logger = logging.getLogger(__name__) # __name__ 是 'myapp.utils'
​
def some_function():
    logger.info("在 utils 模块中执行")

这样日志会清晰地显示来源 myapp.utils - INFO - 在 utils 模块中执行

5、避免重复日志

问题 :如果 Loggerpropagate=True(默认)且父 Logger 也有 Handler,日志可能被多次输出。

解决方案 :在配置中为你的应用 Logger 设置 "propagate": False

处理中文FileHandlerRotatingFileHandler 中指定 encoding="utf-8"

总结

Python 的 logging 模块是一个功能完备、设计精良的日志框架。掌握其核心组件(Logger, Handler, Formatter, Filter)的工作原理,是构建可靠应用的基础。通过合理的配置(尤其是使用 dictConfig 分离配置),你可以轻松实现:

  • 多环境适配 :开发时输出 DEBUG 信息,生产时只输出 WARNING 及以上。

  • 多目标输出:同时将详细日志写入文件,将关键信息输出到控制台。

  • 结构化日志:包含时间、位置、级别等上下文信息,便于排查问题。

  • 可维护性:配置集中管理,易于调整。

告别 print,拥抱 logging,让你的应用拥有清晰、可追溯的"生命日志"!

参考

Python logging 模块 | 菜鸟教程

Python logging 官方文档

相关推荐
骑驴看星星a28 分钟前
数学建模--Topsis(Python)
开发语言·python·学习·数学建模
学习3人组30 分钟前
JupyterLab在线调试实验室
python
ygy.白茶2 小时前
线性回归入门级
人工智能·python·机器学习
刘同学Python学习日记3 小时前
Python 办公自动化实战:Excel 批量处理 + 自动发邮件
python
mit6.8243 小时前
[Vid-LLM] 功能分类体系 | 视频如何被“观看“ | LLM的主要作用
人工智能·python
无规则ai4 小时前
动手学深度学习(pytorch版):第六章节—卷积神经网络(1)从全连接层到卷积
人工智能·pytorch·python·深度学习·cnn
秋难降4 小时前
优雅的代码是什么样的?🫣
java·python·代码规范
二闹5 小时前
聊天怕被老板发现?摩斯密码来帮你
后端·python
mit6.8245 小时前
[RestGPT] OpenAPI规范(OAS)
人工智能·python