Python日志记录库——loguru

本文介绍了Python内置logging库的繁琐配置问题,并推荐了loguru作为替代品。loguru提供简单易用的接口,支持彩色输出、线程/进程安全、模块化命名和自定义格式,以及将日志序列化为json并支持多进程并发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 概述

在 Python 中用到日志记录,那就不可避免地会用到内置的 logging标准库 。虽然logging 库采用的是模块化设计,你可以设置不同的 handler 来进行组合,但是在配置上通常较为繁琐;而且如果不是特别处理,在一些多线程或多进程的场景下使用 logging还会导致日志记录会出现错乱或是丢失的情况。

关于Python内置的 logging标准库介绍可参见博客:Python 日志记录工具logging

标准库logging的替代品是loguru,loguru使用起来就简单的多。它不仅能够减少繁琐的配置过程还能实现和logging类似的功能,同时还能保证日志记录的线程进程安全,又能够和logging 相兼容,并进一步追踪异常也能进行代码回溯。

loguru默认的输出格式是:时间、级别、模块、行号以及日志内容。loguru不需要手动创建 logger,开箱即用;另外,日志输出内置了彩色功能,颜色和非颜色控制很方便,更加友好。

loguru官方文档https://loguru.readthedocs.io/en/stable/index.html
在这里插入图片描述

二、基本使用

2.1 安装

loguru是非标准库,需要事先安装,命令是:

pip install loguru

logger 本身就是一个已经实例化好的对象,如果没有特殊的配置需求,那么自身就已经带有通用的配置参数;同时它的用法和 logging库输出日志时的用法一致。

2.2 日志输出

(1)输出到控制台

安装后,最简单的使用样例如下:

from loguru import logger

logger.debug('hello, this debug loguru')
logger.info('hello, this is info loguru')
logger.warning('hello, this is warning loguru')
logger.error('hello, this is error loguru')
logger.critical('hello, this is critical loguru')

上述代码输出:
在这里插入图片描述

(2)输出到控制台+文件

日志打印到文件的用法也很简单,代码如下:

from loguru import logger

logger.add('myloguru.log')

logger.debug('hello, this debug loguru')
logger.info('hello, this is info loguru')
logger.warning('hello, this is warning loguru')
logger.error('hello, this is error loguru')
logger.critical('hello, this is critical loguru')

上述代码运行时,可以打印到console,也可以打印到文件中去。
在这里插入图片描述

三、进阶用法

3.1 显示格式

loguru默认格式是时间、级别、名称+模块和日志内容,其中名称+模块是写死的,是当前文件的__name__变量,此变量最好不要修改。

工程比较复杂的情况下,自定义模块名称,是非常有用的,容易定界定位,避免陷入细节中。我们可以通过logger.configure手工指定模块名称。如下如下:

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')

上述代码中:

  • handlers:表示日志输出句柄或者目的地,sys.stderr表示输出到命令行终端。
  • “sink”: sys.stderr,表示输出到终端
  • “format”:表示日志格式化。{level:8}</>表示按照日志级别显示颜色。8表示输出宽度为8个字符。
  • “colorize”: True**:表示显示颜色。

上述代码的输出为:
在这里插入图片描述

这里写死了模块名称,每个日志都这样设置也是比较繁琐。下面会介绍指定不同模块名称的方法。

3.2 写入文件

日志一般需要持久化,除了输出到命令行终端外,还需要写入文件。标准日志库可以通过配置文件配置logger,在代码中也可以实现,但过程比较繁琐。loguru相对而已就显得稍微简单一些,我们看下在代码中如何实现此功能。日志代码如下:

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
    },
    {
        "sink": 'first.log',
        "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |{level:8}| {name} : {module}:{line:4} | mymodule | - {message}",
        "colorize": False
    },
])

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')

与3.1 唯一不同的地方,logger.configure新增了一个handler,写入到日志文件中去。用法很简单。

3.3 模块名参数化

上述只是通过logger.configure设置日志格式,但是模块名不是可变的,实际项目开发中,不同模块写日志,需要指定不同的模块名称。因此,模块名称需要参数化,这样实用性更强。样例代码如下:

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>{extra[module_name]}</> | - <lvl>{message}</>",
        "colorize": True
    },
    {
        "sink": 'first.log',
        "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |{level:8}| {name} : {module}:{line:4} | {extra[module_name]} | - {message}",
        "colorize": False
    },
])

log = logger.bind(module_name='my-loguru')
log.debug("this is hello, module is my-loguru")

log2 = logger.bind(module_name='my-loguru2')
log2.info("this is hello, module is my-loguru2")

logger.bind(module_name=‘my-loguru’)通过bind方法,实现module_name的参数化。bind返回一个日志对象,可以通过此对象进行日志输出,这样就可以实现不同模块的日志格式。
loguru中自定义模块名称的功能比标准日志库有点不同。通过bind方法,可以轻松实现标准日志logging的功能。而且,可以通过bind和logger.configure,轻松实现结构化日志。

上述代码的输出如下:
在这里插入图片描述

3.4 日志留存、压缩与清理

通常来说如果程序或服务的量级较大,那么就可以通过集成的日志平台或数据库来对日志信息进行存储和留存,后续有需要的话也方便进行日志分析。

但对我们个人或者一些中小型项目来说,通常只需要以文件的形式留存输出的日志即可。

尽管我们需要将日志写入到相应的文件中,如果是少量的日志那还好,但是如果是日志输出或记录时间较长的情况,那么单个日志文件就十分之大,倘若仍然是将日志都写入到一个文件中,那么当日志中的内容增长到一定数量时我们想要读取并查找相应的部分时就十分困难。这时候我们就需要对日志文件进行留存、压缩,甚至在必要时及时进行清理。

基于以上,我们可以通过对rotationcompressionretention 三个参数进行设定来满足我们的需要:

  • rotation :rotation参数能够帮助我们将日志记录以文件大小、时间等方式进行分割或划分。
# 设置每天 0 点新创建一个 log 文件:
logger.add('runtime_{time}.log', rotation='00:00')

# 设置超过 500 MB 新创建一个 log 文件:
logger.add('runtime_{time}.log', rotation="500 MB")

# 设置每隔一个周新创建一个 log 文件:
logger.add('runtime_{time}.log', rotation='1 week')
  • compression :随着分割文件的数量越来越多之后,我们也可以进行压缩对日志进行留存,这里就要使用到 compression参数,该参数只要你传入通用的压缩文件扩展名即可,如zip、tar、gz等。
# 设置使用 zip 文件格式保存
logger.add('runtime_{time}.log', compression='zip')
  • retention :如果你不想对日志进行留存,或者只想保留一段时间内的日志并对超期的日志进行删除,那么可以使用 retention 参数。
# 设置日志文件最长保留 15 天:
logger.add('runtime_{time}.log', retention='15 days')

# 设置日志文件最多保留 10 个:
logger.add('runtime_{time}.log', retention=10)

# retention的参数也可以是一个 datetime.timedelta 对象,比如设置日志文件最多保留 5 个小时:
import datetime
logger.add('runtime_{time}.log', retention=datetime.timedelta(hours=5))

3.5 序列化为json格式

如果在实际中你不太喜欢以文件的形式保留日志,那么你也可以通过 serialize 参数将其转化成序列化的json格式,最后将导入类似于MongoDB、ElasticSearch 这类数NoSQL 数据库中用作后续的日志分析。

loguru保存成结构化json格式非常简单,只需要设置serialize=True参数即可。代码如下:

from loguru import logger

logger.add('json.log', serialize=True, encoding='utf-8')
logger.debug('this is debug message')
logger.info('this is info message')
logger.error('this is error message')

输出内容如下:
在这里插入图片描述

3.6 并发安全

loguru默认是线程安全的,但不是多进程安全的,如果使用了多进程安全,需要添加参数enqueue=True,样例代码如下:

logger.add("somefile.log", enqueue=True)

参考资料

### 如何在 Allure 中集成 Log 日志记录 为了实现 `Allure` 报告中的日志记录功能,可以通过配置 Python 的标准 `logging` 和第三方 `loguru` 来达成这一目标。具体来说,在测试脚本中引入 `loguru` 并设置自定义的日志处理器来捕获并传递给 `logging` 模块处理。 #### 使用 `loguru` 结合 `logging` 通过创建一个继承自 `logging.Handler` 类的类——`PropogateHandler`,可以在其中重写 `emit()` 方法以便将来自 `loguru` 的日志消息转发至 `logging` 系统[^1]: ```python import logging from loguru import logger class PropagateHandler(logging.Handler): def emit(self, record): # 获取原始日志记录器名称,并将其交给对应的logger实例处理 logging.getLogger(record.name).handle(record) # 添加 PropagateHandler 到 loguru,默认会输出到控制台 logger.add( PropagateHandler(), format="{time:YYYY-MM-DD at HH:mm:ss} | {message}" ) ``` 上述代码片段展示了如何让 `loguru` 输出的内容能够被 `logging` 所接收,从而进一步由 `allure-pytest` 插件捕捉这些信息作为附件附加到最终生成的 HTML 报表里去。 对于希望确保每次运行 pytest 测试框架时都能正常显示完整的日志内容,则建议不要使用 `-s` 参数启动命令行工具;因为该参数会影响标准输入输出流的行为,进而干扰正常的日志收集过程[^2]。 另外值得注意的是,当涉及到移动端应用自动化测试场景下(比如基于 Appium 对 Android 应用做 UI 层面的功能验证),除了基本的日志外还可以考虑加入更多上下文信息辅助排查问题所在,例如页面截图等操作。 最后提醒一下关于持续集成方面的好处:频繁地把个人修改同步回项目主线有助于尽早暴露潜在冲突以及质量问题,使得整个团队能更加高效稳定地推进产品研发进度[^3]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值