告别logging,loguru让你的日志如此优雅
Loguru 是一个现代化的、开箱即用的 Python 日志记录库,旨在让日志记录变得简单、直观、强大。它彻底改变了传统 Python logging 模块的复杂配置模式。
安装
pip install loguruQuickStart
from loguru import logger
import sys
# 移除默认配置(可选)
logger.remove()
# 控制台输出(开发环境)
logger.add(
sys.stderr,
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>",
level="DEBUG",
colorize=True
)
# 文件输出(生产环境)
logger.add(
"logs/app_{time}.log",
rotation="00:00", # 每天午夜轮转
retention="30 days", # 保留30天
compression="zip",
level="INFO",
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} | {message}"
)
# 使用
logger.info("系统启动")
logger.debug(f"参数: {params}")
logger.error("数据库连接失败", user_id=123)移除配置
使logger.remove() 移除配置,remove放在不同的位置会移除不同的配置
import sys
from loguru import logger
# 移除默认配置
logger.remove()
logger.add(
sys.stderr,
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>",
level="DEBUG",
colorize=True
)
# 移除个人配置
logger.remove()核心配置
logger.add()是 loguru 的核心配置方法,用于添加日志处理器(handler),决定日志输出到哪里以及如何格式化。
基本语法:
from loguru import logger
# 基本格式
handler_id = logger.add(
sink, # 输出目标
level="INFO", # 记录级别
format="...", # 格式字符串
filter=None, # 过滤器
colorize=None, # 是否彩色
**kwargs # 其他参数
)sink 参数详解
输出到控制台
import sys
# 输出到标准错误(默认)
logger.add(sys.stderr, level="DEBUG")
# 输出到标准输出
import sys
logger.add(sys.stdout, level="INFO")
# 自定义输出函数
def my_sink(message):
print(f"自定义输出: {message}")
logger.add(my_sink)输出到文件
# 简单文件
logger.add("app.log") # 追加模式
# 带时间戳的文件名
logger.add("app_{time}.log") # app_2023-01-01_12-30-00.log
logger.add("app_{time:YYYY-MM}.log") # app_2023-01.log
# 按大小轮转
logger.add("app.log", rotation="100 MB")
# 按时间轮转
logger.add("app.log", rotation="00:00") # 每天午夜
logger.add("app.log", rotation="1 week") # 每周
logger.add("app.log", rotation="1 month") # 每月
logger.add("app.log", rotation="100 MB 1 day") # 每天或100MB
# 保留策略
logger.add("app.log", retention="10 days") # 保留10天
logger.add("app.log", retention=5) # 保留5个文件
# 压缩旧日志
logger.add("app.log", compression="zip") # zip格式
logger.add("app.log", compression="gz") # gzip格式输出到多种目标
# 同时输出到控制台和文件
logger.add(sys.stderr, level="INFO")
logger.add("app.log", level="DEBUG", rotation="100 MB")
# 不同级别到不同文件
logger.add("info.log", level="INFO", rotation="1 day")
logger.add("error.log", level="ERROR", rotation="10 MB")
logger.add("debug.log", level="DEBUG", retention="5 days")输出到其他系统
# 发送到 HTTP 接口
import requests
def send_to_http(message):
requests.post("https://logs.example.com",
json={"log": message.record})
logger.add(send_to_http)
# 发送到数据库
import sqlite3
def send_to_db(message):
conn = sqlite3.connect("logs.db")
conn.execute("INSERT INTO logs VALUES (?, ?)",
(message.record["time"], message.record["message"]))
conn.commit()
logger.add(send_to_db)format 参数详解
# 默认格式
logger.add(sys.stderr, format="{time} | {level} | {message}")
# 详细格式
logger.add(
sys.stderr,
format="{time:YYYY-MM-DD HH:mm:ss.SSS} | "
"{level: <8} | "
"{name}:{function}:{line} | "
"{message}"
)
# 带颜色的格式(控制台)
logger.add(
sys.stderr,
format="<green>{time}</green> | "
"<level>{level}</level> | "
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | "
"<level>{message}</level>"
)所有可用字段,字段需要加大括号,如{time}
{
"time": "2023-01-01 12:30:00.123", # 时间戳
"level": "INFO", # 级别
"message": "Hello World", # 消息内容
"name": "__main__", # 模块名
"function": "main", # 函数名
"line": 42, # 行号
"file": "app.py", # 文件名
"process": 12345, # 进程ID
"thread": 67890, # 线程ID
"elapsed": 1.234, # 从启动到现在的秒数
"exception": "ZeroDivisionError", # 异常类型
}level 参数详解
# 日志级别从低到高
logger.add("trace.log", level="TRACE") # 最详细
logger.add("debug.log", level="DEBUG") # 调试
logger.add("info.log", level="INFO") # 信息(默认)
logger.add("success.log", level="SUCCESS") # 成功
logger.add("warning.log", level="WARNING") # 警告
logger.add("error.log", level="ERROR") # 错误
logger.add("critical.log", level="CRITICAL") # 严重
# 动态级别
import sys
logger.add(
sys.stderr,
level=lambda record: "DEBUG" if record["function"] == "test" else "INFO"
)filter 参数详解
# 只记录特定模块
logger.add("app.log", filter=lambda record: "my_module" in record["name"])
# 排除特定消息
def no_secrets(record):
message = record["message"]
return "password" not in message and "secret" not in message
logger.add("app.log", filter=no_secrets)
# 按级别过滤
logger.add("app.log", filter=lambda record: record["level"].no >= 30) # >= WARNINGcolorize 参数详解
# 自动检测(默认)
logger.add(sys.stderr, colorize=None)
# 强制彩色
logger.add(sys.stderr, colorize=True)
# 强制无彩色
logger.add(sys.stderr, colorize=False)
# 自定义颜色
logger.add(
sys.stderr,
format="<red>{time}</red> <blue>{message}</blue>",
colorize=True
)序列化输出
`异步应用配置
# FastAPI/Django 配置
logger.add(
"api.log",
rotation="00:00",
format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {extra[request_id]} | {message}",
filter=lambda record: "uvicorn" not in record["name"], # 过滤框架日志
enqueue=True # 多线程安全
)
# 使用
@app.middleware("http")
async def add_log_context(request: Request, call_next):
request_id = request.headers.get("X-Request-ID", "unknown")
with logger.contextualize(request_id=request_id):
response = await call_next(request)
return response高级日志选项控制器
logger.opt()是 loguru 的高级日志选项控制器,允许你临时修改单条日志记录的行为、格式和内容。
from loguru import logger
# opt() 返回一个特殊的记录器实例
special_logger = logger.opt()
# 链式调用
logger.opt(exception=True).error("错误详情")异常处理
exception=True控制是否在日志中包含完整的异常堆栈信息。
# 不记录异常堆栈
try:
1 / 0
except:
logger.error("发生了错误") # 只记录消息,没有堆栈
# 记录异常堆栈
try:
1 / 0
except:
logger.opt(exception=True).error("发生了错误")
# 输出:错误消息 + 完整堆栈跟踪
# 等价于 logger.exception()
logger.opt(exception=True).error("错误") # 等价于 logger.exception("错误")异常深度控制
try:
def inner():
return 1 / 0
inner()
except:
# 只显示最近3层堆栈
logger.opt(exception=True, depth=3).error("错误")
# 不显示堆栈,只显示异常类型
logger.opt(exception=False).error("错误")调用深度
depth=N调整日志记录中文件名、函数名、行号的显示深度。
# utils.py
def helper():
# depth=0: 显示 helper 函数的位置
logger.opt(depth=0).info("helper 被调用")
# depth=1: 显示调用 helper 的位置
logger.opt(depth=1).info("上一级调用")
# depth=2: 显示调用者的上一级
logger.opt(depth=2).info("上上级调用")
# main.py
def main():
helper() # 从 main 调用 helper在depth = 0时,终端中会输出Info | utils.py::xxx行 | helper 被调用 这样的日志,到了depth = 1后,终端中会输出Info | main.py::xxx行 | 上一级调用 这样的日志,以此类推
通常logger.opt(depth=1)这个足够满足大部分的应用场景
访问原始记录
record=True允许在日志消息中访问并修改 record 字典。
# 添加额外字段到当前日志
logger.opt(record=True).info(
"用户 {record[extra][user]} 的操作",
user="Alice"
)
# 动态修改消息
def add_timestamp(message):
message.record["extra"]["timestamp"] = message.record["time"].isoformat()
logger.opt(record=True).info("当前时间: {record[extra][timestamp]}")
# 条件格式化
logger.opt(record=True).info(
"状态: {record[extra][status] if 'status' in record['extra'] else '未知'}"
)延迟计算
lazy=True可以延迟计算日志消息,只在需要记录时才计算(性能优化)。
V颜色控制
colors=True/False强制启用或禁用单条日志的颜色。
import sys
# 配置带颜色的处理器
logger.add(sys.stderr, colorize=True, format="<level>{message}</level>")
# 这条日志有颜色
logger.info("普通信息")
# 这条日志强制无颜色
logger.opt(colors=False).info("无颜色信息")
# 这条日志强制有颜色(即使全局配置colorize=False)
logger.opt(colors=True).info("强制彩色信息")原始输出
raw=True绕过格式化器,直接输出原始消息。
# 普通输出(经过格式化)
logger.add(sys.stderr, format="[INFO] {message}")
logger.info("Hello") # 输出: [INFO] Hello
# 原始输出(绕过格式)
logger.opt(raw=True).info("Hello\n") # 输出: Hello(直接换行)
# 组合使用
logger.opt(raw=True, colors=True).info("<red>错误</red>\n")记录捕获
capture=True/False控制是否捕获并存储日志记录。
# 创建不带捕获的记录器
no_capture_logger = logger.opt(capture=False)
# 这条日志不会被任何处理器捕获
no_capture_logger.info("秘密消息")
# 只被特定处理器捕获
error_logger = logger.opt(capture=lambda: False) # 自定义逻辑输出
基础输出
from loguru import logger
# INFO 级别(默认)
logger.info("这是一条普通信息")
# DEBUG 级别(调试)
logger.debug("调试信息,通常用于开发阶段")
# WARNING 级别
logger.warning("警告信息,需要注意")
# ERROR 级别
logger.error("错误信息,操作失败")
# CRITICAL 级别
logger.critical("严重错误,系统可能无法继续运行")
# SUCCESS 级别(loguru 特有)
logger.success("操作成功!")
# TRACE 级别(最详细)
logger.trace("最详细的跟踪信息")
# 直接使用 log() 方法指定级别
logger.log("INFO", "使用 log 方法指定级别")自动捕获异常
# 方法1:装饰器自动捕获
@logger.catch
def risky_function():
return 1 / 0
# 方法2:上下文管理器
def process_data():
try:
result = 1 / 0
except ZeroDivisionError:
logger.exception("除以零错误") # 自动包含完整堆栈
# 方法3:带级别控制
try:
risky_operation()
except Exception as e:
logger.opt(exception=True).error("操作失败") # 只记录错误级别
# 方法4:详细配置
@logger.catch(level="ERROR", reraise=False)
def critical_function():
# 函数内部异常会被记录但不重新抛出
pass
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
soap的会员制餐厅!
喜欢就支持一下吧