目录
[三、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 核心组件快速使用示例)
[2、RotatingFileHandler 分割日志文件](#2、RotatingFileHandler 分割日志文件)
[4、在多模块项目中使用 name](#4、在多模块项目中使用 name)
引言
在软件开发中,日志(Logging)是不可或缺的工具。它帮助我们追踪程序执行流程、诊断错误、监控系统状态,是调试、运维和分析用户行为的关键。Python 内置的 logging
模块功能强大且灵活,远超简单的**print
** 语句。
一、logging对比print
你可能习惯用 print()
输出信息,但 logging
模块提供了 print
无法比拟的优势:
-
日志级别(Levels) :支持
DEBUG
,INFO
,WARNING
,ERROR
,CRITICAL
等级别,可以方便地控制不同环境(开发、测试、生产)输出的信息量。 -
灵活的输出目标(Handlers) :日志可以同时输出到控制台、文件、网络、邮件、数据库等,而
print
只能输出到标准输出。 -
丰富的格式化(Formatters):可以自定义日志的输出格式,包含时间、模块名、行号、日志级别等信息。
-
性能 :在生产环境中,可以将日志级别设为
WARNING
,此时debug()
调用几乎不消耗性能(因为消息不会被格式化),而print
语句即使注释掉也需要手动操作。 -
结构化与可维护性 :
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
按名称形成树状结构。myapp
是myapp.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
级别是DEBUG
,Handler
级别是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
名称、日志级别或其他属性进行过滤。 -
使用场景 :相对较少直接使用,
Logger
和Handler
的级别通常足够。但可以用于实现复杂逻辑,比如只记录特定用户的日志。
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
会无限增长文件。使用 RotatingFileHandler
或 TimedRotatingFileHandler
可以自动管理日志文件大小和数量。
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、避免重复日志
问题 :如果 Logger
的 propagate=True
(默认)且父 Logger
也有 Handler
,日志可能被多次输出。
解决方案 :在配置中为你的应用 Logger
设置 "propagate": False
。
处理中文 在 FileHandler
或 RotatingFileHandler
中指定 encoding="utf-8"
。
总结
Python 的 logging
模块是一个功能完备、设计精良的日志框架。掌握其核心组件(Logger
, Handler
, Formatter
, Filter
)的工作原理,是构建可靠应用的基础。通过合理的配置(尤其是使用 dictConfig
分离配置),你可以轻松实现:
-
多环境适配 :开发时输出
DEBUG
信息,生产时只输出WARNING
及以上。 -
多目标输出:同时将详细日志写入文件,将关键信息输出到控制台。
-
结构化日志:包含时间、位置、级别等上下文信息,便于排查问题。
-
可维护性:配置集中管理,易于调整。
告别 print
,拥抱 logging
,让你的应用拥有清晰、可追溯的"生命日志"!
参考
Python logging 官方文档