简介
**logging 模块是 Python 标准库里提供的日志功能组件,它是在开发过程中实现日志记录的推荐方式。**logging 模块主要包含四个组件:Logger、Handler、Filter 和 Formatter。通过它们的协作可以快速实现对日志的控制和处理。
组件
Logger
**Logger 是日志模块中最基本的组件,它负责生成和分类日志。**在应用代码中,我们可以通过 getLogger 方法获取 Logger 对象,主要有两种获取方式:
Handler
Handler 用于指定 Logger 生成的日志消息应发送到哪个目标输出,常用的 Handler 有两种:
- StreamHandler:输出到流,如 sys.stdout、sys.stderr
- FileHandler:输出到文件
我们可以通过 Logger 对象的 addHandler 方法将 Handler 与 Logger 关联起来:
Filter
**Filter 用于提供复杂的日志过滤功能,可以用来过滤 INFO、DEBUG 等不同级别的日志。**根据需求,我们可以通过 logger.addFilter 将过滤器加到 logger 或者 handler 里。
Formatter
**Formatter 用于控制日志信息的最终输出格式。**我们可以指定日志不同部分的显示格式,如时间、代码位置、日志消息等。
基础配置
我们可以通过字典或文件的方式配置 logging 模块。
dictConfig 配置
fileConfig 配置
将配置字典写入 json 或 yaml 文件,通过 fileConfig 函数加载:
配置参数
logging 模块的配置参数较多,主要包括以下方面:
参数 | 说明 |
---|---|
version | 配置字典的版本,目前为 1 |
disable_existing_loggers | 是否禁用已存在的其他日志器,默认 False |
formatters | 定义日志信息的格式化样式 |
filters | 定义过滤日志信息的过滤器 |
handlers | 定义日志的处理方法以及目标位置 |
loggers | 定义具体的日志器并绑定处理器和过滤器 |
root | 根日志器配置,其配置会应用到所有日志器上 |
loggers 配置参数:
参数 | 说明 |
---|---|
level | 日志器接收的日志级别 |
handlers | 绑定的日志处理器 |
filters | 绑定的日志过滤器 |
propagate | 是否传递给父日志器,默认 True |
handlers 常用参数:
参数 | 说明 |
---|---|
class | 指定处理器类,如 FileHandler、StreamHandler 等 |
level | 处理器的日志级别 |
formatter | 用于格式化日志的 Formatter |
args | 处理器初始化参数,如文件名等 |
formatters 参数:
参数 | 说明 |
---|---|
format | 指定日志输出格式的模板 |
datefmt | 格式化时间的格式字符串 |
style | 输出样式,如 ’{’ 和 ’$’ 等 |
模块用法
graph TB
START(开始)-->Choose_Logger[选择Logger]
Choose_Logger-->|内置Logger|Use_Builtin[使用Python内置Logger]
Choose_Logger-->|自定义Logger|Define_Logger[定义自定义Logger]
Define_Logger-->Set_Level[设置日志级别<br>如DEBUG,INFO等]
Define_Logger-->Create_Handler[创建Handler<br>如FileHandler,<br>StreamHandler等]
Set_Level-->Create_Handler
Create_Handler-->Set_Format[设置日志格式]
Set_Format-->Add_Handler[添加Handler到Logger]
Use_Builtin-->Set_Level
Use_Builtin-->Create_Handler
Add_Handler--> USE[使用Logger记录日志]
USE-->END(结束)
日志级别
logging 模块总共定义了 6 个级别的日志,按照严重程度从低到高排列如下:
级别 | 数值 | 说明 |
---|---|---|
DEBUG | 10 | 最详细的调试信息 |
INFO | 20 | 确认一切运行正常 |
WARNING | 30 | 表示出现异常,但尚未影响程序运行 |
ERROR | 40 | 由于更严重的问题,程序的某些功能已经不能正常运行了 |
CRITICAL | 50 | 严重错误,程序可能无法继续运行 |
在代码中记录日志时,我们可以根据需要的日志级别选择合适的函数,比如:
日志级别可用于控制日志的输出粒度,通过设置级别参数可以只输出大于或等于该级别的日志。
日志输出
logging 模块支持通过多种 Handler 将日志输出到不同的位置,常见的有两种:
输出到控制台
输出到文件
此外,还可以通过 SocketHandler 进行网络日志,通过 MemoryHandler 将日志输出到内存等。
日志格式化
logging 模块允许自定义日志的输出格式,方便阅读和分析。主要通过 Formatter 实现。
Formatter 使用的格式字符串类似于 C 语言的 printf 格式,可以包含以下字段:
字段 | 说明 |
---|---|
asctime | 日志事件发生时间,如 2023-02-28 15:49:23,895 |
levelname | 日志级别的文本表示,如 INFO、ERROR 等 |
levelno | 日志级别的数值,如 20、40 等 |
message | 日志消息文本 |
pathname | 调用日志输出函数的源代码文件路径 |
filename | pathname 的文件名部分 |
module | 文件名的模块名部分 |
funcName | 调用日志输出函数的函数名 |
lineno | 调用日志输出函数的源代码行号 |
thread | 线程 ID |
process | 进程 ID |
日志高级功能
日志回滚
通过 RotatingFileHandler 可以实现日志文件回滚,即当日志文件达到一定大小时自动生成新文件。
日志分割
它可以设置最大字节数和备份文件的数量,超过这些限制之后就会生成新的日志文件。通过 TimedRotatingFileHandler 可以实现日志文件按时间分割。
通过 when 参数可以设置按日、周、月等时间间隔进行切割,interval 参数设置时间间隔大小。
最佳实践
根据应用场景配置 Logging 模块
不同的 Python 应用场景需要不同的日志方案:
- 小型命令行程序:直接输出到 stdout
- 大型项目:输出到日志文件,同时进行错误提醒、日志分割等
- 分布式系统:实现集中式日志,结合 ELK 等日志分析系统
选择合适的 logging 功能组合。
与项目架构相结合
logging 模块要与项目的架构设计相结合,比如:
- 对 Django 项目进行专门的 Logging 设置
- 对 Flask 项目使用 dictsConfig 进行配置
- 对于大型项目,创建一个 log.py 统一处理日志
可选的日志收集工具
可以结合日志收集系统,实现可视化分析,如 ELK(ElasticSearch + Logstash + Kibana) 组合。
日志的性能优化
- 通过配置只记录必要的日志级别,不记录无用日志
- 将调试日志单独记录到一个文件
- 避免频繁字符串拼接,使用参数化格式
- 控制日志文件大小和滚动频率
实战练习
标准日志模块的配置示范
以上实现了一个标准的日志配置,输出到控制台和文件,并使用不同的格式器,包含日志实践中的常见操作。
小型项目中添加日志
以一个小型的 Web 项目为例:
代码中创建日志器、添加处理器、设置格式后,就可以在项目代码任何地方使用 logger.info、logger.debug 等记录日志,从而方便地添加日志功能。
尝试优化项目日志的性能
优化日志性能的常见做法:
- 通过配置文件配置日志,不要在代码里反复配置
- 设置生产环境只记录必要的日志级别,如 WARNING 以上
- ERROR 日志单独记录到文件,便于定位问题
- DEBUG 日志可以使用内存 Handler,避免 IO 消耗
- 使用异步日志,避免影响程序性能
- 合理设置日志滚动策略,避免文件过大
扩展学习
其他日志框架的比较 (Loguru、log4j 等)
logging 模块作为标准库,用法简单,但需要自行处理诸如异步、日志分割等额外功能。一些第三方日志库如 loguru、log4j 等提供了更多实用功能的封装,可以根据需求选择。
分布式系统日志收集方案
在分布式系统中,可以通过将日志发送到消息队列如 Kafka,然后由 Logstash 收集存储到 ElasticSearch 中,最后结合 Kibana 进行日志分析和可视化。也可以直接使用 ELK 提供的 Filebeat 代替 Logstash 从日志文件中收集日志。