logging 模块升级版 loguru
logging 模块 组成及使用
文章目录
- 一、Loguru 相对于 Logging 的改进(为什么选择 Loguru?)
- 二、loguru 模块 项目简单使用
- 1. 日志输出相关配置
- 2. 项目各子模块间日志隔离
一、Loguru 相对于 Logging 的改进(为什么选择 Loguru?)
标准库的 logging
模块非常强大和灵活,是许多大型项目和框架的基石。然而,它的配置和使用方式也相当繁琐和复杂。Loguru 的核心设计哲学就是为开发者提供一个开箱即用、配置更简单、更符合直觉的日志系统。可以说是logging的高级封装。
-
开箱即用,无需繁琐配置
- Logging: 你需要手动创建
Logger
、设置日志级别、配置Handler
、Formatter
和Filter
。一个基本的配置可能就需要十多行代码。 - Loguru: 直接从
loguru
导入logger
实例即可开始记录日志,所有基础配置(如输出到 stderr、格式、级别)都已预设好。
- Logging: 你需要手动创建
-
更简洁友好的输出格式
- Logging: 默认格式较为简单,需要手动配置才能获得丰富信息(如时间、级别、模块、行号)。
- Loguru: 默认提供了色彩丰富、信息详尽的日志输出,包括时间、级别、模块、行号和日志信息,视觉上更易于阅读。
-
更容易地输出到文件
-
Logging: 需要创建
FileHandler
并将其添加到logger
中。import logging import sys # 日志配置 logging.basicConfig(format='{asctime}:{levelname} {name}.py {message}', datefmt='%Y-%m-%d %H:%M:%S',style='{',level=logging.DEBUG,stream=sys.stdout) # 日志输出 logger = logging.getLogger('test') logger.info('日志提示信息')
-
Loguru: 只需要一个
add()
方法调用,即可轻松添加文件日志,并支持强大的日志文件管理功能(如循环、压缩、 retention 清理等)。from loguru import logger logger.remove() # 移除默认配置 logger.add(sink=sys.stdout) logger.info('日志提示信息')
-
-
更安全的多进程日志记录
- Logging: 在多进程环境下,如果使用
FileHandler
可能会遇到日志内容交错或丢失的问题,需要额外的处理(如QueueHandler
)。 - Loguru: 内部处理了多进程并发写入的问题,默认就是安全的。
- Logging: 在多进程环境下,如果使用
-
使用
catch
装饰器自动记录异常-
Logging: 记录函数异常通常需要在函数内部使用
try...except
并手动记录error
。import logging logger = logging.getLogger('追踪错误') try:res = 2/0 except Exception:logger.error('failed',exc_info=True) # 设置参数exc_info
-
Loguru: 使用一个简单的装饰器
@logger.catch
即可自动捕获并记录函数中发生的任何异常,包括完整的堆栈跟踪。from loguru import logger@logger.catch() def cal():return 20/0 cal()
-
-
更方便的运行时日志修改
- 通过
add()
,remove()
方法可以非常动态地添加或删除日志 sink(输出目标),而无需重新配置整个日志系统。
- 通过
二、loguru 模块 项目简单使用
1. 日志输出相关配置
# utils.py
from loguru import logger# 日志存储路径
log_file_path = 'xxxx'# 日志配置函数
def setup_logger(log_file_path=None):logger.remove() # 移除默认配置(避免重复输出)if log_file_path:# 配置文件日志处理器logger.add(sink=log_file_path, # 日志文件路径rotation="100 MB", # 按大小分割retention="30 days", # 保留30天level='INFO', # 日志记录级别format='<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>', filter=None,colorize=None,serialize=False,backtrace=True,diagnose=True,enqueue=False,)# 同时输出到控制台logger.add(sink=sys.stdout, # 标准控制台输出level='INFO', # 日志记录级别format='<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>', filter=None,colorize=True)return logger
2. 项目各子模块间日志隔离
在默认情况下,你从不同文件导入的 logger
对象是同一个全局单例对象。
- 全局唯一性:整个 Python 解释器进程中,只有一个
loguru.logger
实例。 - 配置共享:你在任何一个文件中对这个
logger
进行的配置(比如添加 sink、设置级别、修改格式),都会立即在所有其他导入了logger
的文件中生效。 - 线程安全:Loguru 的全局
logger
是线程安全的,你可以在多线程环境中安全地使用它,而无需担心日志信息错乱。
# 不同模块不同日志配置(假设3个子模块 a、b、c)
# utils.pyfrom loguru import logger
import os# 日志基础路径
base_path = 'xxx'
# 不同应用日志存储路径
apps = [('app_a','a'),('app_b','b'),('app_c','c')]def setup_logger(): logger.remove() # 移除默认配置(避免重复输出)for app,app_log_path in apps:# 为每个app创建不同存储路径log_file_path = os.path.join(base_path,app_log_path)os.makedirs(log_file_path,exist_ok=True)# 日志存储文件名称log_file_name = os.path.join(log_file_path,'{time:YYYY-MM-DD}.log')# 为日志配置存储格式logger.add(sink=log_file_name,level='INFO',rotation='00:00', # 指示何时关闭当前日志文件和何时开启新文件的条件retention="30 days", # 设置日志保留时间,自动清理format='{time:YYYY-MM-DD HH:mm:ss} - {extra[label]} - {level} - {message}', # label 为logger.bind函数为日志绑定的额外键值对标签enqueue=True, # 异步写入,提高性能filter=lambda record,label=app: print(record["extra"]) or record['extra'].get('label') == label # 分别添加3个日志过滤器,为3个应用进行日志过滤分流 (print 打印调试使用) )# 日志初始化
setup_logger()
# main.py from utils import logger# 日志记录器绑定上应用标签
logger.bind(label='app_a').error('a应用日志信息')
logger.bind(label='app_b').info('b应用日志信息')
logger.bind(label='app_c').info('c应用日志信息')# 生成日志文件
-- XXX- a- 2025-09-11.log # 2025-09-11 01:39:14 - app_a - ERROR - a应用日志信息- b- 2025-09-11.log # 2025-09-11 01:39:14 - app_b - INFO - b应用日志信息- c- 2025-09-11.log