1. 介绍
日志记录是软件开发中的一个重要环节,它可以帮助我们监控程序运行过程中的状态、诊断问题以及分析性能。Python 中通常使用 logging 模块,让我们能够方便地记录日志信息。
2. 案例与日志级别
在举例子之前先介绍以下日志级别,日志级别的高低可以通过数值表示,数值越高,日志级别越高。打开logging的源码可以发现,这些日志等级实际上是整数常量,因此比如logging.ERROR
和40
在代码里面也就是等价的:
由上可知:
DEBUG < INFO < WARNING < ERROR < CRITICAL
日志级别 | 数值 | 描述 |
---|---|---|
DEBUG | 10 | 详细的诊断信息,用于开发和调试阶段 |
INFO | 20 | 一般性的信息,例如程序启动、关闭或完成某个操作 |
WARNING | 30 | 潜在的问题或异常情况,但并不会导致程序中断 |
ERROR | 40 | 导致程序中断或无法完成某个操作的错误 |
CRITICAL | 50 | 非常严重的错误,可能导致整个系统崩溃或数据丢失 |
接着一个简单的例子:
代码语言:javascript复制import logging
# 配置 logging 模块
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 记录日志信息
logging.debug("This is a debug message.")
logging.info("This is an info message.")
logging.warning("This is a warning message.")
logging.error("This is an error message.")
logging.critical("This is a critical message.")
在这个例子中,先使用 basicConfig()
进行初始化基本配置。我们设置了日志级别为 INFO,这意味着所有级别大于或等于 INFO的日志信息都会被输出(DEBUG不会输出)。
运行这个示例,将在控制台看到如下输出:
代码语言:javascript复制2023-11-16 13:16:32,871 - INFO - This is an info message.
2023-11-16 13:16:32,873 - WARNING - This is a warning message.
2023-11-16 13:16:32,873 - ERROR - This is an error message.
2023-11-16 13:16:32,874 - CRITICAL - This is a critical message.
这里有一点需要注意,如果是在jupyter上测试。第一次运行完之后修改basicConfig()
里面的日志等级并不会改变。因为logging.basicConfig()
只会在第一次调用时设置日志记录器的配置。后续对 basicConfig()
的调用将被忽略。这时候如果想要修改日志等级,则需要使用:
logging.getLogger().setLevel(logging.ERROR)
3. 配置和自定义日志记录
在了解如何使用自定义 logging 之前,需要了解一些基本概念:
- Logger:Logger 是 logging 模块的核心对象,用于记录日志信息。通常,我们会为每个模块或组件创建一个 Logger 对象。Logger 对象之间可以形成层次结构,以便更好地管理日志记录。
- Handler:Handler 对象负责将日志信息输出到不同的目的地,例如控制台、文件或网络。一个 Logger 可以有多个 Handler,以实现不同级别的日志输出。
- Formatter:Formatter 对象用于定义日志信息的格式。我们可以自定义 Formatter,以便按照需要展示日志信息。
- Filter:Filter 对象用于对日志信息进行过滤,以便有选择地输出日志。
下面是一个例子:
代码语言:javascript复制import logging
# 创建一个名为 'my_logger' 的 Logger 对象
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)
# 创建一个 Handler,输出日志到控制台
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 创建一个 Handler,输出日志到文件
file_handler = logging.FileHandler('my_log.log')
file_handler.setLevel(logging.DEBUG)
# 创建一个 Formatter,定义日志信息的格式
console_formatter = logging.Formatter('我在控制台里面!%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_formatter = logging.Formatter('我在文件里面!%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 为 Handler 设置 Formatter
console_handler.setFormatter(console_formatter)
file_handler.setFormatter(file_formatter)
# 为 Logger 添加 Handler
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# 记录日志信息
logger.debug("This is a debug message.")
logger.info("This is an info message.")
logger.warning("This is a warning message.")
logger.error("This is an error message.")
logger.critical("This is a critical message.")
logging.StreamHandler()
是输出日志到控制台,logging.FileHandler('my_log.log')
是输出日志到文件可以分别使用不同的formatter,最终展示效果如下。
4. 高级用法
logging 模块还提供了一些高级功能,例如日志过滤、日志旋转等。
4.1 日志过滤
我们可以使用 Filter 对象对日志信息进行过滤,有选择地输出日志:
代码语言:javascript复制class CustomFilter(logging.Filter):
def filter(self, record):
# 只输出包含 'important' 关键字的日志信息
return 'important' in record.msg
# 为 Logger 添加自定义 Filter
logger.addFilter(CustomFilter())
# 记录日志信息
logger.info("This is an important info message.")
logger.info("This is a regular info message.")
这里重写了 filter()
方法,使其只允许包含 'important' 关键字的日志信息通过。
4.2 日志旋转
在长时间运行的程序中,日志文件可能会变得非常大。为了避免这个问题,可以使用日志旋转功能,这个在平时开发中很常见。logging 模块提供了一个 RotatingFileHandler
类,用于实现日志文件的自动旋转。以下是一个示例:
from logging.handlers import RotatingFileHandler
# 创建一个 RotatingFileHandler,最多保留 5 个日志文件,每个文件最大 1MB
rotating_handler = RotatingFileHandler('rotating_log.log', maxBytes=1024 * 1024, backupCount=5)
rotating_handler.setLevel(logging.DEBUG)
rotating_handler.setFormatter(formatter)
# 为 Logger 添加 RotatingFileHandler
logger.addHandler(rotating_handler)
# 记录日志信息
for i in range(10000):
logger.debug(f"This is a debug message {i}.")
多次运行以上代码后,可以发现目录下生成多个文件,且rotating_log.log
是最新文件。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!