Python Loguru 使用指南

Loguru 是一个非常好用的 Python 日志库。相比标准库 logging,它最大的特点是:

  • 配置简单,开箱即用
  • 日志格式友好
  • 支持文件轮转、压缩、保留策略
  • 支持异常堆栈追踪
  • 支持结构化上下文
  • 支持异步/多进程场景
  • 可以方便地拦截标准 logging
  • 特别适合 Web 服务、脚本、爬虫、数据处理和 CLI 项目

安装

bash 复制代码
pip install loguru

验证:

bash 复制代码
python -c "from loguru import logger; logger.info('Hello Loguru')"

输出类似:

text 复制代码
2026-08-28 15:56:20.123 | INFO     | __main__:<module>:1 - Hello Loguru

最基本的使用

Loguru 不需要创建 Logger 实例。

直接:

python 复制代码
from loguru import logger

logger.debug("这是 debug 日志")
logger.info("程序启动")
logger.warning("这是警告")
logger.error("发生错误")
logger.critical("严重错误")

默认会输出到 stderr

常用级别:

Level 用途
TRACE 非常详细的调试信息
DEBUG 调试信息
INFO 正常运行信息
SUCCESS 成功操作
WARNING 警告
ERROR 普通错误
CRITICAL 严重错误

例如:

python 复制代码
logger.trace("进入函数")
logger.debug("user_id={}", user_id)
logger.info("用户登录成功")
logger.success("订单创建成功")
logger.warning("磁盘空间不足")
logger.error("数据库连接失败")
logger.critical("服务无法启动")

Loguru 最重要的特性:格式化

Loguru 推荐使用 {}

python 复制代码
name = "Alice"
age = 20

logger.info("用户 {} 的年龄是 {}", name, age)

输出:

text 复制代码
用户 Alice 的年龄是 20

也可以使用关键字:

python 复制代码
logger.info(
    "用户 {name} 的年龄是 {age}",
    name="Alice",
    age=20,
)

不要过度使用 f-string

可以这样:

python 复制代码
logger.info(f"user_id={user_id}")

但更推荐:

python 复制代码
logger.info("user_id={}", user_id)

因为 Loguru 自己负责格式化。

支持复杂对象

python 复制代码
user = {
    "id": 1001,
    "name": "Alice",
    "roles": ["admin", "user"],
}

logger.info("用户信息:{}", user)

添加日志文件

这是实际项目中最常见的需求。

python 复制代码
from loguru import logger

logger.add("app.log")

logger.info("程序启动")
logger.error("发生错误")

此时日志会同时:

text 复制代码
终端
+
app.log

日志文件轮转

生产环境千万不要让一个日志文件无限增长。

Loguru 可以:

python 复制代码
logger.add(
    "app.log",
    rotation="10 MB",
)

意思是:

日志文件达到 10 MB 后自动创建新文件。

也可以按时间:

python 复制代码
logger.add(
    "app.log",
    rotation="00:00",
)

每天零点轮转。

或者:

python 复制代码
logger.add(
    "app.log",
    rotation="1 day",
)

常见 rotation

python 复制代码
rotation="10 MB"
rotation="1 GB"
rotation="1 day"
rotation="1 week"
rotation="00:00"

例如:

python 复制代码
logger.add(
    "logs/app_{time}.log",
    rotation="100 MB",
)

日志保留策略

比如只保留最近 30 天:

python 复制代码
logger.add(
    "logs/app.log",
    rotation="100 MB",
    retention="30 days",
)

或者只保留 10 个日志文件:

python 复制代码
logger.add(
    "logs/app.log",
    retention=10,
)

日志压缩

生产环境非常推荐开启压缩:

python 复制代码
logger.add(
    "logs/app.log",
    rotation="100 MB",
    retention="30 days",
    compression="zip",
)

生成的旧日志可能类似:

text 复制代码
app.log
app.2026-08-28_15-00-00.log.zip
app.2026-08-27_15-00-00.log.zip

支持常见压缩格式,例如:

python 复制代码
compression="zip"
compression="gz"
compression="tar.gz"

推荐的生产级配置

一个普通 Python 项目可以直接使用:

python 复制代码
from pathlib import Path

from loguru import logger


LOG_DIR = Path("logs")
LOG_DIR.mkdir(exist_ok=True)


logger.add(
    LOG_DIR / "app.log",
    rotation="100 MB",
    retention="30 days",
    compression="zip",
    encoding="utf-8",
    enqueue=True,
)

其中:

python 复制代码
enqueue=True

非常值得注意。

它可以让日志写入通过队列处理,在多线程/多进程程序中通常更加安全。

自定义日志格式

例如:

python 复制代码
logger.add(
    "app.log",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
)

输出:

text 复制代码
2026-08-28 15:20:31 | INFO | 程序启动
2026-08-28 15:20:32 | ERROR | 数据库连接失败

常用 format 字段

text 复制代码
{time}
{level}
{message}
{name}
{module}
{function}
{line}
{process}
{thread}
{file}

例如:

python 复制代码
logger.add(
    "app.log",
    format=(
        "{time:YYYY-MM-DD HH:mm:ss.SSS} | "
        "{level:<8} | "
        "{name}:{function}:{line} | "
        "{message}"
    ),
)

可能得到:

text 复制代码
2026-08-28 15:30:21.123 | INFO     | main:start:20 | 服务启动

彩色日志

终端中可以:

python 复制代码
logger.info("<green>启动成功</green>")
logger.warning("<yellow>磁盘空间不足</yellow>")
logger.error("<red>连接失败</red>")

也可以使用:

python 复制代码
logger.add(
    "app.log",
    colorize=False,
)

通常:

终端可以彩色,文件日志不要彩色。

异常日志:Loguru 的杀手级功能

普通:

python 复制代码
try:
    1 / 0
except Exception as e:
    logger.error("发生异常:{}", e)

虽然可以,但堆栈信息不完整。

推荐:

python 复制代码
try:
    1 / 0
except Exception:
    logger.exception("计算失败")

输出:

text 复制代码
ERROR 计算失败
Traceback (most recent call last):
  ...
ZeroDivisionError: division by zero

logger.exception() 非常重要

例如:

python 复制代码
def test():
    data = {}
    return data["name"]


try:
    test()
except Exception:
    logger.exception("执行 test 失败")

你可以获得完整 traceback。

这比:

python 复制代码
logger.error(str(e))

好很多。

@logger.catch

Loguru 提供了一个非常方便的装饰器:

python 复制代码
from loguru import logger


@logger.catch
def divide(a, b):
    return a / b


divide(10, 0)

发生异常时 Loguru 会自动记录 traceback。

更适合程序入口

例如:

python 复制代码
@logger.catch
def main():
    run_server()
    process_data()
    start_worker()


if __name__ == "__main__":
    main()

这样没有被捕获的异常也可以自动记录。

控制 catch 是否重新抛出异常

例如:

python 复制代码
@logger.catch(reraise=True)
def test():
    raise ValueError("测试异常")

这样:

  1. Loguru 记录异常
  2. 异常继续向上抛

对于很多应用程序来说:

python 复制代码
@logger.catch(reraise=True)

是比较合理的选择。

日志级别过滤

例如只记录 WARNING 以上:

python 复制代码
logger.add(
    "error.log",
    level="WARNING",
)

这样:

python 复制代码
logger.info("不会写入")
logger.warning("会写入")
logger.error("会写入")

不同日志文件

实际项目可以:

python 复制代码
logger.add(
    "logs/info.log",
    level="INFO",
)

logger.add(
    "logs/error.log",
    level="ERROR",
)

于是:

text 复制代码
info.log
  INFO
  WARNING
  ERROR

error.log
  ERROR
  CRITICAL

只记录 ERROR

如果希望严格只记录某一级别,可以使用过滤器:

python 复制代码
logger.add(
    "logs/error.log",
    filter=lambda record: record["level"].name == "ERROR",
)

根据模块过滤

例如:

python 复制代码
logger.add(
    "database.log",
    filter=lambda record: record["name"] == "database",
)

不过在大型项目中,我更推荐使用 bind() / contextualize() 搭配业务字段。

bind():给日志绑定上下文

这是 Loguru 很实用的功能。

例如一个请求:

python 复制代码
request_logger = logger.bind(request_id="abc123")

request_logger.info("收到请求")
request_logger.info("开始查询数据库")
request_logger.info("请求处理完成")

日志中可以通过格式显示:

python 复制代码
logger.add(
    "app.log",
    format="{time} | request_id={extra[request_id]} | {message}",
)

得到:

text 复制代码
request_id=abc123 | 收到请求
request_id=abc123 | 开始查询数据库
request_id=abc123 | 请求处理完成

contextualize():临时上下文

例如:

python 复制代码
with logger.contextualize(request_id="abc123"):
    logger.info("开始处理")
    logger.info("查询数据库")
    logger.info("处理完成")

在这个 with 作用域内,日志都自动带上:

text 复制代码
request_id=abc123

Web 项目中特别有用

比如:

python 复制代码
def handle_request(request_id):
    with logger.contextualize(request_id=request_id):
        logger.info("开始请求")
        process()
        logger.info("请求完成")

这样你不需要每次:

python 复制代码
logger.info("request_id={} 开始请求", request_id)
logger.info("request_id={} 查询数据库", request_id)
logger.info("request_id={} 请求完成", request_id)

代码会干净很多。

extra 自定义字段

可以:

python 复制代码
logger.bind(
    user_id=1001,
    request_id="abc123",
).info("用户操作")

然后:

python 复制代码
logger.add(
    "app.log",
    format=(
        "{time} | "
        "{level} | "
        "{extra} | "
        "{message}"
    ),
)

输出类似:

text 复制代码
INFO | {'user_id': 1001, 'request_id': 'abc123'} | 用户操作

结构化日志

如果日志最终要进入:

  • Elasticsearch
  • Loki
  • Splunk
  • Datadog
  • 云日志平台

可以考虑 JSON。

例如:

python 复制代码
import sys
from loguru import logger

logger.remove()

logger.add(
    sys.stdout,
    serialize=True,
)

logger.bind(
    user_id=1001,
    request_id="abc123",
).info("用户登录")

Loguru 会输出 JSON 风格的数据。

这对于日志平台非常方便。

将标准 logging 接入 Loguru

这是实际项目中非常重要的一点。

很多第三方库使用:

python 复制代码
import logging

logging.getLogger(__name__).info("xxx")

而你的项目使用 Loguru。

可以把标准 logging 转发到 Loguru。

一种常见方式:

python 复制代码
import logging
import sys

from loguru import logger


class InterceptHandler(logging.Handler):

    def emit(self, record):
        level = record.levelname

        try:
            level = logger.level(level).name
        except ValueError:
            level = "INFO"

        logger.opt(depth=6, exception=record.exc_info).log(
            level,
            record.getMessage(),
        )


logging.basicConfig(
    handlers=[InterceptHandler()],
    level=0,
    force=True,
)

这样第三方库的:

python 复制代码
logging.info(...)

也可以统一进入 Loguru。

FastAPI / Uvicorn 项目

如果你使用 FastAPI,通常会遇到:

text 复制代码
FastAPI
Uvicorn
standard logging
Loguru

多套日志系统的问题。

可以统一到 Loguru。

例如:

python 复制代码
from loguru import logger


logger.remove()

logger.add(
    "logs/app.log",
    rotation="100 MB",
    retention="30 days",
    compression="zip",
    enqueue=True,
    encoding="utf-8",
)

然后配置标准 logging 拦截。

这样应用层和很多依赖库的日志就能统一。

多进程

如果你使用:

python 复制代码
multiprocessing

或者:

text 复制代码
Gunicorn
Celery
多进程 Worker

建议:

python 复制代码
logger.add(
    "logs/app.log",
    enqueue=True,
)

enqueue=True 会通过队列将日志写入串行化,避免多个进程同时写日志造成问题。

异步程序

例如:

python 复制代码
async def main():
    logger.info("开始执行")

    await do_something()

    logger.info("执行完成")

Loguru 可以正常用于 asyncio。

如果日志量很大,可以考虑:

python 复制代码
logger.add(
    "logs/app.log",
    enqueue=True,
)

删除默认 Handler

Loguru 默认已经存在一个 handler。

如果你:

python 复制代码
logger.add("app.log")

那么实际上是:

text 复制代码
默认 handler
      ↓
终端

新增 handler
      ↓
app.log

如果你想完全自己控制:

python 复制代码
logger.remove()

然后:

python 复制代码
logger.add(
    sys.stdout,
    level="INFO",
)

logger.add(
    "logs/app.log",
    level="DEBUG",
)

一个比较完整的 logging.py

实际项目我比较推荐把日志配置单独放一个文件:

text 复制代码
project/
├── app/
│   ├── __init__.py
│   ├── main.py
│   └── service.py
│
├── logs/
│
├── logging_config.py
└── requirements.txt

logging_config.py

python 复制代码
import sys
from pathlib import Path

from loguru import logger


LOG_DIR = Path("logs")
LOG_DIR.mkdir(parents=True, exist_ok=True)


def setup_logging():
    logger.remove()

    # 控制台
    logger.add(
        sys.stderr,
        level="INFO",
        format=(
            "<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
            "<level>{level: <8}</level> | "
            "{name}:{function}:{line} | "
            "<level>{message}</level>"
        ),
    )

    # 普通日志
    logger.add(
        LOG_DIR / "app.log",
        level="INFO",
        rotation="100 MB",
        retention="30 days",
        compression="zip",
        encoding="utf-8",
        enqueue=True,
    )

    # 错误日志
    logger.add(
        LOG_DIR / "error.log",
        level="ERROR",
        rotation="50 MB",
        retention="30 days",
        compression="zip",
        encoding="utf-8",
        enqueue=True,
    )

    return logger

然后:

python 复制代码
# main.py

from loguru import logger

from logging_config import setup_logging


setup_logging()


def main():
    logger.info("应用启动")

    try:
        1 / 0
    except Exception:
        logger.exception("执行失败")


if __name__ == "__main__":
    main()

一个容易踩坑的问题:重复 add()

不要在多个模块里反复:

python 复制代码
logger.add("app.log")

例如:

python 复制代码
# a.py
logger.add("app.log")

# b.py
logger.add("app.log")

# c.py
logger.add("app.log")

可能造成:

text 复制代码
一条日志
↓
写一次
↓
写两次
↓
写三次

正确做法是:

整个应用统一初始化一次 Loguru。

业务模块只:

python 复制代码
from loguru import logger

然后直接使用。

推荐项目结构

比较成熟的项目:

text 复制代码
project/
│
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── api/
│   ├── services/
│   ├── models/
│   └── utils/
│
├── config/
│   └── settings.py
│
├── logs/
│   ├── app.log
│   └── error.log
│
├── core/
│   └── logging.py
│
└── requirements.txt

core/logging.py

python 复制代码
import sys
from pathlib import Path

from loguru import logger


def setup_logging():
    log_dir = Path("logs")
    log_dir.mkdir(exist_ok=True)

    logger.remove()

    logger.add(
        sys.stderr,
        level="INFO",
    )

    logger.add(
        log_dir / "app.log",
        rotation="100 MB",
        retention="30 days",
        compression="zip",
        enqueue=True,
        encoding="utf-8",
    )

    logger.add(
        log_dir / "error.log",
        level="ERROR",
        rotation="100 MB",
        retention="90 days",
        compression="zip",
        enqueue=True,
        encoding="utf-8",
    )

然后应用入口:

python 复制代码
from core.logging import setup_logging

setup_logging()

业务代码:

python 复制代码
from loguru import logger


def create_order(order_id):
    logger.info("创建订单 {}", order_id)

    try:
        ...
    except Exception:
        logger.exception(
            "创建订单失败,order_id={}",
            order_id,
        )
        raise

日志设计建议

实际开发中,不要把 Loguru 当成 print()

不推荐:

python 复制代码
logger.info("开始")
logger.info("1")
logger.info("2")
logger.info("3")
logger.info("结束")

日志太碎。

推荐:

python 复制代码
logger.info(
    "订单创建成功,order_id={},user_id={}",
    order_id,
    user_id,
)

让一条日志表达一个有意义的事件

推荐日志内容

例如:

text 复制代码
用户登录成功
订单创建成功
支付成功
数据库连接失败
Redis 连接超时
任务执行完成
文件上传失败
HTTP 请求异常

而不是:

text 复制代码
进入函数
变量是 xxx
执行到这里
if 成立

后者属于 Debug 日志。

INFO / DEBUG / WARNING / ERROR 怎么区分?

可以简单记:

text 复制代码
DEBUG
↓
开发人员调试程序

INFO
↓
程序正常发生的重要事件

WARNING
↓
程序还能继续运行,但需要注意

ERROR
↓
某个操作失败

CRITICAL
↓
整个系统可能无法继续工作

例如:

python 复制代码
logger.debug("SQL 参数:{}", params)

logger.info("用户登录成功 user_id={}", user_id)

logger.warning("Redis 响应时间过长:{} ms", elapsed)

logger.error("订单支付失败 order_id={}", order_id)

logger.critical("数据库主库无法连接")

性能方面

如果日志很多:

python 复制代码
logger.debug("data={}", huge_data)

Loguru 支持 lazy=True

python 复制代码
logger.opt(lazy=True).debug(
    "data={}",
    lambda: expensive_operation(),
)

只有 DEBUG 日志实际需要输出时,才执行:

python 复制代码
expensive_operation()

对于计算昂贵的日志内容比较有用。

logger.opt() 常用功能

异常

python 复制代码
logger.opt(exception=True).error("发生错误")

lazy

python 复制代码
logger.opt(lazy=True).debug(
    "result={}",
    lambda: expensive_operation(),
)

depth

python 复制代码
logger.opt(depth=1).info("hello")

在封装日志函数时比较有用,可以让 Loguru 显示真正调用日志的代码位置。

自定义日志函数

例如你不希望业务代码到处出现复杂格式:

python 复制代码
def log_request(method, path, status):
    logger.info(
        "HTTP {} {} status={}",
        method,
        path,
        status,
    )

使用:

python 复制代码
log_request("GET", "/api/users", 200)

如果使用这种封装,推荐:

python 复制代码
logger.opt(depth=1).info(...)

避免日志显示的是 log_request() 的位置,而不是业务调用位置。

Loguru 和标准 logging 对比

功能 logging Loguru
开箱即用
简单配置
文件轮转
压缩 需额外处理
异常追踪 一般 ⭐⭐⭐⭐⭐
上下文 较繁琐
彩色日志 需配置
JSON 需配置
多进程 配置较复杂 enqueue=True
第三方库兼容 原生 可拦截
标准库生态 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐

如果是新项目:

Loguru 很值得直接使用。

如果是大型企业项目:

也可以继续使用标准 logging,尤其当项目已经有完善的 logging 基础设施时。

我比较推荐的生产配置

如果你只是想找一个可以直接复制到项目里使用的方案,可以从这个开始:

python 复制代码
import sys
from pathlib import Path

from loguru import logger


def setup_logging():
    log_dir = Path("logs")
    log_dir.mkdir(parents=True, exist_ok=True)

    logger.remove()

    # Console
    logger.add(
        sys.stderr,
        level="INFO",
        format=(
            "{time:YYYY-MM-DD HH:mm:ss.SSS} | "
            "{level:<8} | "
            "{name}:{function}:{line} | "
            "{message}"
        ),
    )

    # Application log
    logger.add(
        log_dir / "app.log",
        level="INFO",
        rotation="100 MB",
        retention="30 days",
        compression="zip",
        encoding="utf-8",
        enqueue=True,
    )

    # Error log
    logger.add(
        log_dir / "error.log",
        level="ERROR",
        rotation="100 MB",
        retention="90 days",
        compression="zip",
        encoding="utf-8",
        enqueue=True,
    )

    return logger

入口:

python 复制代码
from loguru import logger

from core.logging import setup_logging


setup_logging()


@logger.catch(reraise=True)
def main():
    logger.info("应用启动")

    # 业务逻辑
    logger.info("开始执行任务")

    ...


if __name__ == "__main__":
    main()

业务模块只需要:

python 复制代码
from loguru import logger


def process(user_id):
    logger.info("开始处理 user_id={}", user_id)

    try:
        ...
    except Exception:
        logger.exception(
            "处理失败 user_id={}",
            user_id,
        )
        raise

核心原则可以浓缩成 5 条:

  1. 入口统一初始化一次 logger
  2. 业务模块直接 from loguru import logger
  3. 异常优先用 logger.exception()
  4. 生产环境开启 rotation + retention + compression
  5. 多线程/多进程场景开启 enqueue=True
相关推荐
青 春 记 忆16 分钟前
零基础入门python36:用 Django Session 实现购物车
python·django·后端开发
l12586533 分钟前
# LangGraph Tool Calling Agent 深度实战:从零构建 ReAct 循环与工具调用链
人工智能·python·自然语言处理·langchain·agent
reasonsummer41 分钟前
【办公类-119-03】20260901三个园区“国旗下讲话” 按班级组合docx模板(AI+excel+python、deepseek和豆包、微信自动私发)
python
慢云智慧空间1 小时前
从设备联网到空间理解,智能建筑的系统架构正在经历哪些关键变化?
python·系统架构
磁场转动100万匹3 小时前
PyTorch 手写数字识别实战:从数据加载到模型训练(零基础详解版)
人工智能·pytorch·python
青 春 记 忆9 小时前
零基础入门python30:Flask个人账本从空目录运行与阶段验收
python·flask·后端开发
l1258659 小时前
# LangGraph Memory机制深度解析:短期记忆与长期记忆的工程实践
前端·人工智能·python·langchain·bootstrap
金銀銅鐵11 小时前
斐波那契数列的个位数出现的周期是多少?
python·数学
whcyhhh12 小时前
头歌实践教学平台:数据科学与大数据技术导论(十二)
大数据·开发语言·python·数据清洗