惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
F
Fortinet All Blogs
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
V
Visual Studio Blog
小众软件
小众软件
有赞技术团队
有赞技术团队
雷峰网
雷峰网
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
AWS News Blog
AWS News Blog
C
Cisco Blogs
美团技术团队
T
Threat Research - Cisco Blogs
C
CERT Recently Published Vulnerability Notes
人人都是产品经理
人人都是产品经理
宝玉的分享
宝玉的分享
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
W
WeLiveSecurity
D
DataBreaches.Net
博客园 - 司徒正美
Blog — PlanetScale
Blog — PlanetScale
IT之家
IT之家
云风的 BLOG
云风的 BLOG
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Simon Willison's Weblog
Simon Willison's Weblog
Google DeepMind News
Google DeepMind News
T
The Blog of Author Tim Ferriss
Know Your Adversary
Know Your Adversary
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Vercel News
Vercel News
月光博客
月光博客
T
Tailwind CSS Blog
H
Help Net Security
aimingoo的专栏
aimingoo的专栏
P
Proofpoint News Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cisco Talos Blog
Cisco Talos Blog
Microsoft Security Blog
Microsoft Security Blog
V
V2EX
WordPress大学
WordPress大学
Cyberwarzone
Cyberwarzone
Recent Announcements
Recent Announcements

又见苍岚

COLMAP PatchMatch Stereo 算法详解 事件驱动的状态机框架:从理论到工程实践 Git 在国内网络环境下无法 Push 的排查与修复 —— 配置 Clash 代理 分段五次多项式插值原理详解 路径插值方法深度对比研究 Claude Code 使用指南 OpenClaw 记忆管理与技能创建指南 CBS(Conflict-Based Search)算法详解 A* 算法及其变种详解 OpenClaw 配置多 Agents Windows Powershell 无法加载文件,因为在此系统上禁止运行脚本问题的解决方案 MaxClaw 安装流程 大模型 AI 名词介绍 AList 网盘聚合工具简介 Protobuf 简介与测试 Claude Code 简介以及 GLM 4.7 模型接入 Github 歌词下载工具 163MusicLyrics Python __getattr__ 懒加载 Python TypedDict 机器人仿真平台 Gazebo 安装记录 机器人仿真平台 Gazebo 简介 多机器人路径规划问题(Multi-Agent Path Finding, MAPF)简介 Python exifread 读取修改过的 jpeg 信息错误问题修复 3D 坐标系变换的理解 3D 旋转矩阵基本概念 MongoDB Compass 介绍 Python 环境管理工具 uv Flutter 开发指南 Snipaste 安装下载与黑屏问题解决方案 全局路径规划算法记录 2025 Python 版本性能测试 Flutter Hello World Flutter 安装环境配置 Ubuntu VMware 硬盘扩容后 SMBus Host controller not enabled 报错问题解决 Python NetworkX 教程 Docker GPU 报错 - Failed to initialize NVML Unknown Error 解决方案 Python matplotlib 图表绘制 cuda-toolkit 安装替代 Cuda 与 Cudnn Jinja2 Python 利用 docxtpl 和 Jinja2 生成基于模板的 Word 文档 Docker 实现 CPU 核心隔离 LoFTR 基于 Transformer 的特征提取匹配算法 OmniGlue 特征匹配 SuperGlue 使用图神经网络学习特征匹配 Ubuntu 下将 xlsx 文件按照 sheet 转换为 图片 Python 使用 SQLAlchemy Python FastAPI 教程 openwrt 软路由配置安装 Nav2 地图文件(PGM/YAML)规范标准 3D OBJ 模型转换为 glb 瓦片格式 Python 源码 Redis 数据库介绍 Ubuntu 22.04 内核自动升级导致 MongoDB 7.0.12 错误记录 ubuntu 20.04 安装 ROS Noetic ubuntu 18.04 安装 ROS Melodic VMware Workstation Pro 个人免费版下载、安装、使用指南 Hybrid A-star 路径规划 Reeds-Shepp 曲线 Dubins 曲线 Linux kvm 虚拟机网络不通的问题解决方法 Ubuntu 自动内存清理 BiliBili 缓存视频转 mp4 Python 求解线性规划 3D Gaussian Splatting 官方源码实践记录 ImageMagick 教程 Ubuntu 22.04 安装 Colmap 对数几率 odds Ubuntu nmcli 网络管理工具使用指南 SuperPoint 自监督深度学习特征点提取 SyncTV Music Tag Web 在线音乐信息整理工具 ncm 格式转 mp3 MusicBrainz 音乐元数据百科数据库 Ubuntu 网络流量监控工具 私人云音乐平台 Navidrome 入门 手眼标定 四元数(Quaternions) OHTTPS 实现免费自动 https 证书申请、更新、部署 ubuntu 22.04 安装 CloudCompare 单机 KVM 虚拟机冷迁移 Ubuntu 22.04 使用 mdadm 实现软 raid 小鱼 一键安装 ROS-humble Fluid -46- 基于 Simpletex API 构建公式识别页面 公式识别 API 简介 -- Simpletex 使用 Python web 部署库 waitress 3D Gaussian Splatting for Real-Time Radiance Field Rendering Ubuntu Swap 简介与空间扩展 Ubuntu 24.04 安装 forticlient Clash Verge 使用 MongoDB 7.0.17 集群 Docker 构建源码 Error code - 2013. Lost connection to MySQL server during query 问题解决 Python 实现 Web 日志查看服务 MySQL LOAD DATA LOCAL INFILE 极速数据加载 Image size exceeds limit of 89478485 pixels 解决方案 Docker 使用 NVIDIA GPU 驱动错误解决 阿里云 docker 镜像仓库 Ubuntu中没有wired connected的解决方案 MinIO 简介 subconverter 代理订阅格式转换 修复 node –openssl-legacy-provider is not allowed in NODE_OPTIONS 错误 Ubuntu 使用 Clash For Linux 客户端
Python 日志记录库 loguru 使用指北
Yiwei Zhang · 2025-04-09 · via 又见苍岚

Loguru是一个功能强大且易于使用的开源Python日志记录库。本文记录相关内容。

简介

Loguru是一个功能强大且易于使用的开源Python日志记录库。它建立在Python标准库中的logging模块之上,并提供了更加简洁直观、功能丰富的接口。

Loguru的主要特点包括:

  • 简单易用:无需复杂的配置和定制即可实现基本的日志记录和输出。
  • 灵活的日志格式:支持自定义日志格式,并提供丰富的格式化选项。
  • 丰富的日志级别:支持多种日志级别,例如DEBUG、INFO、WARNING、ERROR和CRITICAL。
  • 多种日志目标:可以将日志输出到终端、文件、电子邮件、网络服务器等目标。
  • 强大的日志处理功能:支持日志过滤、格式化、压缩、旋转等功能。
  • 支持异步日志记录:能够极大地提升日志记录的性能。
  • 支持跨进程、跨线程的日志记录:可以安全地记录多进程、多线程应用程序的日志。

Loguru与logging是Python中常用的两个日志记录库,但两者在功能和易用性方面存在一些差异,如下所示:

特性 Loguru logging
易用性 更简单易用 相对复杂
日志格式 更灵活 较简单
日志级别 更丰富 较少
日志目标 更多种类 较少
日志处理功能 更强大 较弱
异步日志记录 支持 不支持
跨进程、跨线程支持 支持 支持

总的来说,loguru在易用性、功能性和性能方面都优于logging。如果要一个简单、强大且易于使用的日志系统,loguru是一个很好的选择。

基础使用

安装方法

1
pip install loguru

设计理念

Loguru的核心概念是只有一个全局的日志记录器,也就是 logger。这个设计使得日志记录变得非常简洁和一致。使用Loguru时,你不需要创建多个日志实例,而是直接使用这个全局的logger来记录信息。这不仅减少了配置的复杂性,也使得日志管理更加集中和高效。

1
2
3
from loguru import logger

logger.debug("这是一个调试信息")

默认格式

Loguru日志输出默认格式如下:

  1. 时间戳:表示日志记录的具体时间,格式通常为年-月-日 时:分:秒.毫秒。
  2. 日志级别:表示这条日志的严重性级别。
  3. 进程或线程标识:表示日志来自哪个模块或脚本。 __main__ 表示日志来自主模块。如果是其他文件会显示文件名。
  4. 文件名和行号:记录日志消息的函数名和行号。
  5. 日志消息:实际的日志内容,此外loguru支持使用颜色来区分不同的日志级别,使得日志输出更加直观.

日志等级

Loguru可以通过简单的函数调用来记录不同级别的日志,并自动处理日志的格式化和输出。这一特点可以让使用者专注于记录重要的信息,而不必关心日志的具体实现细节。Loguru支持的日志级别,按照从最低到最高严重性排序:

  • TRACE: 最详细的日志信息,用于追踪代码执行过程。Loguru默认情况下使用DEBUG级别作为最低日志记录级别,而不是TRACE级别。这是因为TRACE级别会产生大量的日志信息。
  • DEBUG: 用于记录详细的调试信息,通常只在开发过程中使用,以帮助诊断问题。
  • INFO: 用于记录常规信息,比如程序的正常运行状态或一些关键的操作。
  • SUCCESS: 通常用于记录操作成功的消息,比如任务完成或数据成功保存。
  • WARNING: 用于记录可能不是错误,但需要注意或可能在未来导致问题的事件。
  • ERROR: 用于记录错误,这些错误可能会影响程序的某些功能,但通常不会导致程序完全停止。
  • CRITICAL: 用于记录非常严重的错误,这些错误可能会导致程序完全停止或数据丢失。
1
2
3
4
5
6
7
8
9
from loguru import logger

logger.debug("这是一条跟踪消息")
logger.debug("这是一条调试信息")
logger.info("这是一条普通信息")
logger.success("操作成功完成")
logger.warning("这是一条警告信息")
logger.error("这是一条错误信息")
logger.critical("这是一条严重错误信息")

多模块使用

由于在 loguru 中有且仅有一个对象:logger。所以loguru是可以在多块module文件中使用的,而且不会出现冲突。

所有添加至logger的sink默认都是线程安全的,所以loguru也可以很安全的在多线程的情形下使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#coding:utf-8

from atexit import register
from random import randrange
from threading import Thread, Lock, current_thread
from time import sleep, ctime

from loguru import logger

class CleanOutputSet(set):
def __str__(self):
return ','.join(x for x in self)

lock = Lock()
loops = (randrange(2, 5) for x in range(randrange(3, 7)))
remaining = CleanOutputSet()

def loop(nsec):
myname = current_thread().name

logger.info("Startted {}", myname)

'''
锁的申请和释放交给with上下文管理器
'''
with lock:
remaining.add(myname)
sleep(nsec)

logger.info("Completed {} ({} secs)", myname, nsec)

with lock:
remaining.remove(myname)
logger.info("Remaining:{}", (remaining or 'NONE'))

'''
_main()函数是一个特殊的函数,只有这个模块从命令行直接运行时才会执行该函数(不能被其他模块导入)
'''
def _main():
for pause in loops:
Thread(target=loop, args=(pause,)).start()

'''
这个函数(装饰器的方式)会在python解释器中注册一个退出函数,也就是说,他会在脚本退出之前请求调用这个特殊函数
'''
@register
def _atexit():
logger.info("All Thread DONE!")
logger.info("\n===========================================================================\n")

if __name__=='__main__':
logger.add("run.log")

_main()

日志配置

add 添加处理器

在 loguru 中,add函数用于添加日志处理器。这个函数用于指定日志消息应该被发送到何处,例如控制台、文件或其他自定义的目的地。add函数主要参数介绍如下:

  • sink: 定义日志消息的输出位置,可以是文件路径、标准输出(stdout)、标准错误(stderr,默认)或其他自定义的输出位置。
  • format: 指定日志消息的格式,可以是简单的字符串,也可以是格式化字符串,支持各种字段插值。
  • level: 设置处理程序处理的日志消息的最低级别。比如设置为DEBUG,则处理程序将处理所有级别的日志消息。
  • filter: 可选参数,用于添加过滤器,根据特定的条件过滤掉不需要的日志消息。
  • colorize: 布尔值,指定是否对日志消息进行着色处理,使日志在控制台中更易于区分。
  • serialize: 布尔值,指定是否对日志消息进行序列化处理,通常与enqueue=True一起使用,以确保多线程安全。
  • enqueue: 布尔值,指定是否将日志消息放入队列中处理,用于多线程应用中避免阻塞。
  • backtrace: 布尔值或字符串,指定是否记录回溯信息,默认为False
  • diagnose: 布尔值,启用后,会在处理程序内部出现错误时记录诊断信息。
  • rotation: 日志文件轮换的配置,支持按大小或时间进行日志文件的轮换。
  • retention: 用于设置日志文件的保留时间。
  • compression: 布尔值,指定是否对轮换后的日志文件进行压缩处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
from loguru import logger
import sys

# 终端显示不受该段代码设置
# 添加一个日志处理器,输出到文件
# 设置日志最低显示级别为INFO,format将设置sink中的内容
# sink链接的本地文件,如不存在则新建。如果存在则追写
logger.add(sink="myapp.log", level="INFO", format="{time:HH:mm:ss} | {message}| {level}")

# debug结果不被显示到本地文件
logger.debug("这是一条调试信息")
logger.info("这是一条普通信息")

当连续两次调用 add 函数时,loguru 会将新的日志处理器添加到处理器列表中,而不是覆盖之前的处理器。这意味着所有添加的处理器都会接收到日志消息,并且按照它们被添加的顺序来处理这些消息。

1
2
3
4
5
6
from loguru import logger
logger.add(sink="myapp1.log", level="INFO")
logger.add(sink="myapp2.log", level="INFO")
# 会同时存入所有add添加日志处理器
logger.info("这是一条普通信息,存入myapp2")

如果想删除所有已添加的日志处理器,loguru运行使用 logger.remove()方法不带任何参数来移除所有日志处理器。

1
2
3
4
5
6
7
8
9
10
from loguru import logger
import sys

# 移除所有日志处理器(包括终端输出)
logger.remove()
logger.add(sink="myapp3.log", level="INFO", format="{time:HH:mm:ss} | {message}| {level}")

logger.debug("这是一条调试信息存入myapp3")
logger.info("这是一条普通信息存入myapp3")

注意调用logger.remove()之后的所有日志将不会被记录,因为没有处理器了。

1
2
3
4
5
6
from loguru import logger
# 移除所有日志处理器(包括终端输出)
logger.remove()
# 没有输出
logger.info("这是一条普通信息存入myapp3")

如果希望移除某些日志处理器,而不是从所有日志器中移除,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from loguru import logger

# 移除默认终端logger,如果终端存在。
# logger.remove(0)
# 添加多个文件处理器,enqueu设置异步日志记录
handler1 = logger.add("myapp1.log", enqueue=True)
print(handler1) # handler_id是移除的处理器的唯一标识符
handler2 = logger.add("myapp2.log")

# 记录一些日志
logger.info("这些信息会被记录到两个文件中")

# 移除特定的文件处理器
logger.remove(handler1)

# 现在只有myapp2.log 会记录日志
logger.info("这条信息只会记录在myapp2.log 中")

如果想将日志输出到日志台,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from loguru import logger
import sys

logger.remove() # 移除默认输出
# 添加一个日志处理器,输出到控制台,使用自定义格式
logger.add(
sink=sys.stdout,
level="DEBUG",
# green表示颜色
format="<green>{time:HH:mm}</green> <level>{message}</level>"
)

# 注意终端显示会同步显示
logger.debug("这是一条调试信息")
logger.info("这是一条普通信息")

时间自定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from datetime import datetime
from loguru import logger

# 自定义时间格式
# time_format = "%Y-%m-%d %H:%M:%S,%f" # 包括微秒
time_format = "%H:%M:%S,%f" # 包括微秒但不含年月日

# 定义日志格式,使用 datetime.now().strftime() 来格式化时间
log_format = "{time:" + time_format + "} - {level} - {message}"
logger.add("myapp.log", format=log_format, level="DEBUG")

# 记录一条日志
logger.debug("这是一个带有微秒的测试日志")

日志轮换

rotation 滚动记录日志文件

通过配置rotation参数,指定日志文件滚动记录的条件

1
logger.add("file_1.log", rotation="500 MB")    # Automatically rotate too big file

通过这样的配置我们就可以实现每 500MB 存储一个文件,每个 log 文件过大就会新创建一个新的 log 文件。我们可以在创建文件的时候加一个(time)占位符,这样在生成时可以自动将时间替换进去,生成一个文件名包含时间的 log 文件。

1
logger.add("file_2.log", rotation="12:00")     # New file is created each day at noon

通过上面的配置,可以实现没填中午12:00创建一个log文件输出了。

1
logger.add("file_3.log", rotation="1 week")

通过上面的配置可以实现每隔1周创建一个新的log文件输出了。

retention 指定日志保留时长

通过配置retention参数,可以指定日志的保留时长:

1
logger.add("file_X.log", retention="10 days")  # Cleanup after some time

通过上面的配置,就可以指定日志最多保留10天,每隔10天之后就会清理旧的日志,这样就不会造成内存浪费。

compression 配置文件压缩格式

通过配置compression参数可以指定日志文件的压缩格式:

1
logger.add("file_Y.log", compression="zip")    # Save some loved space

通过上面的配置,可以指定日志文件的压缩格式为zip格式,可以节省存储空间。

汇总
1
2
3
4
5
6
7
8
9
10
11
12
from loguru import logger
# 当文件大小达到100MB时创建新的日志文件,旧文件保留并重命名,用于防止单个日志文件变得过大。
logger.add("file_1.log", rotation="100 MB")
# 每天中午12时创建新的日志文件,旧文件保留并重命名
logger.add("file_2.log", rotation="12:00")
# 当日志文件存在超过一周时创建新的日志文件,旧文件保留并重命名
logger.add("file_3.log", rotation="1 week")
# 设置日志文件保留10天
logger.add("file_4.log", retention="10 days")
# 当文件大小达到100MB时创建新的日志文件,旧文件保留压缩为zip文件
logger.add('file_{time}.log', rotation="100 MB", compression='zip')

进阶使用

异常捕获

@logger.catch 装饰器可以用来装饰my_function函数,并将这些异常信息记录到日志中。

1
2
3
4
5
6
7
8
9
from loguru import logger

logger.add(sink='myapp.log')

@logger.catch
def my_function(x, y):
return x / y

res = my_function(0,0)

exception

通过exception方法也可以实现异常的捕获与记录:

1
2
3
4
5
6
7
8
9
10
11
from loguru import logger

logger.add("runtime.log")

def my_function1():
try:
return 1 / 0
except Exception as e:
logger.exception(f"What?! {e}")

my_function1()

输出日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2025-04-09 17:11:36.156 | ERROR    | __main__:my_function1:9 - What?! division by zero
Traceback (most recent call last):

File "/home/vvd/anaconda3/envs/boeye/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
│ │ └ {'__name__': '__main__', '__doc__': None, '__package__': '', '__loader__': <_frozen_importlib_external.SourceFileLoader objec...
│ └ <code object <module> at 0x7681d4e42130, file "/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs...
└ <function _run_code at 0x7681d4e46e60>
File "/home/vvd/anaconda3/envs/boeye/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
│ └ {'__name__': '__main__', '__doc__': None, '__package__': '', '__loader__': <_frozen_importlib_external.SourceFileLoader objec...
└ <code object <module> at 0x7681d4e42130, file "/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs...

File "/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/__main__.py", line 71, in <module>
cli.main()
│ └ <function main at 0x7681d3b21510>
└ <module 'debugpy.server.cli' from '/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs/debugpy/ada...

File "/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 501, in main
run()
└ <function run_file at 0x7681d3b212d0>

File "/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 351, in run_file
runpy.run_path(target, run_name="__main__")
│ │ └ '/home/vvd/Works/lab/loguru/logtest.py'
│ └ <function run_path at 0x7681d40840d0>
└ <module '_pydevd_bundle.pydevd_runpy' from '/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs/de...

File "/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 310, in run_path
return _run_module_code(code, init_globals, run_name, pkg_name=pkg_name, script_name=fname)
│ │ │ │ │ └ '/home/vvd/Works/lab/loguru/logtest.py'
│ │ │ │ └ ''
│ │ │ └ '__main__'
│ │ └ None
│ └ <code object <module> at 0x7681d3c06d90, file "/home/vvd/Works/lab/loguru/logtest.py", line 1>
└ <function _run_module_code at 0x7681d4053d00>

File "/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 127, in _run_module_code
_run_code(code, mod_globals, init_globals, mod_name, mod_spec, pkg_name, script_name)
│ │ │ │ │ │ │ └ '/home/vvd/Works/lab/loguru/logtest.py'
│ │ │ │ │ │ └ ''
│ │ │ │ │ └ None
│ │ │ │ └ '__main__'
│ │ │ └ None
│ │ └ {'__name__': '__main__', '__doc__': None, '__package__': '', '__loader__': None, '__spec__': None, '__file__': '/home/vvd/Wor...
│ └ <code object <module> at 0x7681d3c06d90, file "/home/vvd/Works/lab/loguru/logtest.py", line 1>
└ <function _run_code at 0x7681d4053910>

File "/home/vvd/.vscode/extensions/ms-python.debugpy-2025.6.0-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 118, in _run_code
exec(code, run_globals)
│ └ {'__name__': '__main__', '__doc__': None, '__package__': '', '__loader__': None, '__spec__': None, '__file__': '/home/vvd/Wor...
└ <code object <module> at 0x7681d3c06d90, file "/home/vvd/Works/lab/loguru/logtest.py", line 1>

File "/home/vvd/Works/lab/loguru/logtest.py", line 11, in <module>
my_function1()
└ <function my_function1 at 0x7681d39725f0>

> File "/home/vvd/Works/lab/loguru/logtest.py", line 7, in my_function1
return 1 / 0

ZeroDivisionError: division by zero

自定义日志级别

loguru允许我们自定义日志级别,可以通过logger.level()函数来添加自定义日志级别。例如,我们可以添加一个名为TRACE的日志级别,并将其显示.

1
2
3
4
5
6
7
8
from loguru import logger

# 添加自定义日志级别
logger.level("TRACE", no=5, color="<blue>", icon="🐞")

# 使用自定义日志级别
logger.trace("this is a trace log")

在上面的示例中,我们使用logger.level()函数添加了一个名为TRACE的日志级别,并将其显示为蓝色并带有一个小虫子图标。然后,我们使用logger.trace()方法输出了一条自定义级别的日志信息。

过滤

使用loguru库进行Python日志记录时,可以通过自定义的filter函数来筛选并记录特定的日志信息。此函数接收一个记录对象作为参数,根据日志消息内容(message)、级别(level)或其他日志属性,返回布尔值以决定是否记录该条日志。如果函数返回True,则日志被记录;若返回False,则忽略该日志。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from loguru import logger

# 定义一个过滤器函数
def my_filter(record):
# 只记录包含 "第一" 的日志
return "第一" in record["message"]

# 使用过滤器
logger.add("myapp.log", filter=my_filter)

# 记录一些日志
logger.info("第一个记录")
logger.info("第二个记录")

此外可以结合bind方法进行过滤,bind方法用于向日志记录器添加额外的上下文信息。这些信息将被包含在每条日志消息中,但不会改变日志消息本身。如下所示:

1
2
3
4
5
6
7
8
9
10
11
from loguru import logger

def filter_user(record):
return record["extra"].get("user") =="A"

logger.add("myapp.log", filter=filter_user)

# 绑定user
logger.bind(user="A").info("来自A")
logger.bind(user="B").info("来自B")

还可以使用lambda函数直接配置filter参数,一个完整的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from loguru import logger

# 设置不同级别的日志输出文件
logger.add("debug.log", level="DEBUG", rotation="10 MB", filter=lambda record: record["level"].name == "DEBUG")
logger.add("info.log", level="INFO", rotation="10 MB", filter=lambda record: record["level"].name == "INFO")
logger.add("warning.log", level="WARNING", rotation="10 MB", filter=lambda record: record["level"].name == "WARNING")
logger.add("error.log", level="ERROR", rotation="10 MB", filter=lambda record: record["level"].name == "ERROR")
logger.add("critical.log", level="CRITICAL", rotation="10 MB", filter=lambda record: record["level"].name == "CRITICAL")

# 输出不同级别的日志消息
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")

绑定参数

logger.bind()方法用于绑定参数到日志记录器中,这些参数可以在日志信息中引用。例如,我们可以使用logger.bind()方法绑定一个user_id参数,并在日志信息中引用该参数,示例如下:

1
2
3
4
5
6
7
8
from loguru import logger

# 绑定一个user_id参数
logger = logger.bind(user_id=12345)

# 输出带有user_id参数的日志信息
logger.info("user {user_id} logged in")

在上面的示例中,我们使用logger.bind()方法绑定了一个user_id参数,并使用logger.info()方法输出了一条带有user_id参数的日志信息。

输出日志到指定目标

logger.sink()方法用于将日志记录器的输出发送到指定的目标,例如文件、网络等。例如,我们可以使用logger.sink()方法将日志记录器的输出发送到一个网络套接字中,示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from loguru import logger

# 创建一个网络套接字
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 9000))

# 将日志记录器的输出发送到网络套接字中
logger.add(sock.sendall)

# 输出日志信息
logger.info("hello world")

在上面的示例中,我们创建了一个网络套接字,并使用logger.add()方法将日志记录器的输出发送到该套接字中。接着,我们使用logger.info()方法输出了一条日志信息,该信息将被发送到网络套接字中。

日志不在控制台输出

因为logger是默认输出至stderr的,所以只需要在之前把它给remove掉就好了:

1
2
3
4
5
6
7
from loguru import logger

logger.remove(handler_id=None)

logger.add("runtime.log") # 创建了一个文件名为runtime的log文件

logger.debug("This's a log message in file")

参考资料

文章链接:
https://www.zywvvd.com/notes/coding/python/python-loguru/python-loguru/