Python loguru

Python loguru

在使用Python进行程序开发的过程中,会遇到需要记录的日志的需求,常常会用到Python自带的logging模块,但是logging需要我们进行不同的初始化等相关工作。对应不熟悉该模块的同学来说,还是有些费劲的,比如需要配置 Handler/Formatter 等。而且随着业务的复杂度提升, 对日志收集有着更高的要求, 例如: 日志分类, 文件存储, 异步写入, 自定义类型等等。

loguru 是一个 Python 简易且强大的第三方日志记录库,该库旨在通过添加一系列有用的功能来解决标准记录器的注意事项,从而减少 Python 日志记录的痛苦。

loguru

Installation

1
pip install loguru

log to console

1
2
3
4
5
6
from loguru import logger

logger.debug("That's it, beautiful and simple logging!")

#console print
#2024-01-14 08:47:45.344 | DEBUG | __main__:<module>:3 - That's it, beautiful and simple logging!

log formatiing

loguru默认格式是时间、级别、名称+模块和日志内容,其中名称+模块是写死的,一般场景下不建议修改,但在业务复杂的场景下,自定义模块名称,是非常有用的,我们可以通过logger.configure手工指定模块名称。如下如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import sys

from loguru import logger

logger.configure(handlers=[
{
"sink": sys.stderr,
"format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | <cyan>mymodule</> | - <lvl>{message}</>",
"colorize": True
},
])

logger.debug('this is debug')
logger.info('this is info')
logger.warning('this is warning')
logger.error('this is error')
logger.critical('this is critical')
logger.info("this is {}", "a info log")
logger.info("this is {}", 3)
logger.info("this is {:.2f}", 3)
1
2
3
4
5
6
7
8
import sys
from loguru import logger

logger.remove()
logger.add(sys.stdout, format="{time:YYYY-MM-DD at HH:mm:ss} | <red>{level}</red> | <green>{file}</green> | <b><i>{message}</i></b>")
logger.info("Hello, world!")
logger.info("Hello, {name}!", name="everyone")

format 中,可以通过 {param} 的形式设置内容,通过 <tag></tag> 的形式设置格式。

常见的内容参数有:

参数 含义
time 时间
level 日志等级
file 文件名
message 日志信息
path 文件路径
function 函数
line 行数
module 模块
process 进程信息
thread 线程信息
tzinfo 时区信息
exception 异常信息

log to file

1
2
3
logger.add("log/file_1.log")  # sink

logger.info("this is a info log")

log rotation

1
2
3
4
5
6
7
8
logger.add("log/file_2.log", rotation='10 KB')

for i in range(100):
logger.info("this is a info log")
logger.debug("this is a debug log")
logger.warning("this is a warning log")
logger.error("this is a error log")
logger.critical("this is a critical log")

关于rptation参数还有常见的如下用法:

1
2
3
4
logger.add("log.log", rotation="50 MB")      # 文件超过50M则另起一个文件
logger.add("log.log", rotation="00:00") # 每天00:00另起一个文件
logger.add("log.log", rotation="1 week") # 每周另起一个文件
logger.add("log.log", rotation="10 days") # 每10天另起一个文件

其他常用设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# retention 参数可以设置日志保存时间,到时间后日志会自动清理,注意与 rotation 区分
logger.add("log.log", retention="10 days")

# compression 可以对关闭的日志(如 rotation 处理的日志)进行压缩,节约空间
logger.add("log.log", compression="zip")

# enqueue=True 可以支持异步写入,实现多进程安全
logger.add("log.log", enqueue=True)

# filter 参数可以设置日志的过滤规则
# 过滤不包含 hello 的日志
logger.add("log.log", filter=lambda x: "hello" not in x["message"])

# encoding 设置编码方式
# level 设置日志等级,大于该等级的日志会被记录
logger.add("log.log", encoding="utf-8", level="INFO")

#异步写入
logger.add("log.log", enqueue=True)

#序列化为json写入
logger.add("log1.log", serialize=True)

常用的推荐设置

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

logger_dir = "./log" # 这里是日志的存放目录,需要根据你的项目进行修改

log_path = os.path.join(logger_dir, f'{time.strftime("%Y%m")}', '{time:YYYY_MM_DD}.log')
logger.add(
log_path,
rotation="00:00",
retention="30 days",
enqueue=True,
encoding="utf-8",
level="INFO"
)

与PyTest结合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pytest
from _pytest.logging import LogCaptureFixture
from loguru import logger

def some_func(i, j):
logger.info('Oh no!')
logger.info('haha')
return i + j

@pytest.fixture
def caplog(caplog: LogCaptureFixture):
handler_id = logger.add(caplog.handler, format="{message}")
yield caplog
logger.remove(handler_id)

def test_some_func_logs_warning(caplog):
assert some_func(-1, 3) == 2
assert "Oh no!" in caplog.text

简单封装日志方法

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


# 获取项目路径
def get_pro_path():
pro_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
return pro_path


def get_logger():
logger.add(os.path.join(get_pro_path(), "mytest.log"), rotation="500 MB")
return logger

pytest case调用

1
2
3
4
5
6
7
8
9
10
11
12
"""
loguru使用
"""
from public_fun.log_fun import get_logger
from assertpy import assert_that
logger = get_logger()


def test_fun1():
logger.info('我需要比较1')
assert_that(1).is_not_equal_to(1)


Python loguru
https://skynetboys.github.io/2024/01/14/Python-loguru/
Author
Edison
Posted on
January 14, 2024
Licensed under