ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

更优雅的日志模块logurn

2022-08-01 18:32:29  阅读:163  来源: 互联网

标签:log loguru 28 logurn 2021 模块 日志 logger


logurn更为优雅的python日志管理模块

logging配置起来十分的繁琐,感觉并不是一个优雅的实现方式。

有需求就有动力啊,这不,就有人实现了这么一个库,叫做 loguru,可以将 log 的配置和使用更加简单和方便。

特点

  • 滚动日志
  • 自动压缩日志文件
  • 定时删除
  • 输出高亮显示
  • 字符串格式化
  • 日志序列化
  • 多线程安全
  • 异常追溯
  • 邮件告警

安装

使用 pip 安装即可,Python 3 版本的安装如下:

pip3 install loguru

基本使用

logurn这里直接实例化logger就可以了,但logging需要手动配置才行,从这里就可以看出logurn比logging优雅太多了

from loguru import logger

logger.debug('This is debug information')
logger.info('This is info information')
logger.warning('This is warn information')
logger.error('This is error information')

loguru 在输出的不同级别信息时,带上了不同的颜色,使得结果更加直观,其中也包含了时间、级别、模块名、行号以及日志信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mPBZfiIk-1636610434781)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211111100934418.png)]

loguru 中不同日志级别与日志记录方法对应关系 如下:

级别名称 严重指数 记录器方法
TRACE 5 logger.trace()
DEBUG 10 logger.debug()
INFO 20 logger.info()
SUCCESS 25 logger.success()
WARNING 30 logger.warning()
ERROR 40 logger.error()
CRITICAL 50 logger.critical()

loguru 配置日志文件

在logging中我们需要手动配置Handler,但在loggurn中我们只需要调用logger.add()方法就可以了.

logger 默认采用 sys.stderr 标准错误输出将日志输出到控制台中,假如想要将日志同时输出到其他的位置,比如日志文件,此时我们只需要使用一行代码即可实现。

logger默认日志输出等级是debug

from loguru import logger
# 这里的rotation是一个分割日志,当日志文件达到500MB的时候他会重新创建一个新的文件
# enqueue是一个多进程安全什么什么东西,主要应用在多个进程同时写入一个日志文件
# retention是日志保留时间
logger.add("test.log",rotation="500MB", encoding="utf-8", enqueue=True, retention="10 days")

logger.info('This is info information')

当rotation满足要求的时候就自动将日志文件保存为文件名+日期+.log的格式保存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rvccoXzU-1636610434785)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211111102601049.png)]

日志内容字符串格式化

loguru 在输出 日志的时候,还提供了非常灵活的字符串格式化输出日志的功能,如下:

import platform
from loguru import logger

rounded_value = round(0.345, 2)

trace= logger.add('2021-3-28.log')

logger.info('If you are using Python {version}, prefer {feature} of course!', version=platform.python_version(), feature='f-strings')

# 执行上述代码,输出结果为
2021-03-28 13:43:26.232 | INFO     | __main__:<module>:9 - If you are using Python 3.7.6, prefer f-strings of course!

loguru日志常用参数配置解析

  • sink:可以传入一个 file 对象(file-like object),或一个 str 字符串或者 pathlib.Path 对象,或一个方法(coroutine function),或 logging 模块的 Handler(logging.Handler)。
  • level (int or str, optional) :应将已记录消息发送到接收器的最低严重级别。
  • format (str or callable, optional) :格式化模块,在发送到接收器之前,使用模板对记录的消息进行格式化。
  • filter (callable, str or dict, optional) :用于决定每个记录的消息是否应该发送到接收器。
  • colorize (bool, optional) – 是否应将格式化消息中包含的颜色标记转换为用于终端着色的Ansi代码,或以其他方式剥离。如果None,根据水槽是否为TTY自动作出选择。
  • serialize (bool, optional) :在发送到接收器之前,记录的消息及其记录是否应该首先转换为JSON字符串。
  • backtrace (bool, optional) :格式化的异常跟踪是否应该向上扩展,超出捕获点,以显示生成错误的完整堆栈跟踪。
  • diagnose (bool, optional) :异常跟踪是否应该显示变量值以简化调试。在生产中,这应该设置为“False”,以避免泄漏敏感数据。
  • enqueue (bool, optional) :要记录的消息在到达接收器之前是否应该首先通过多进程安全队列。当通过多个进程将日志记录到文件中时,这是非常有用的。这还具有使日志调用非阻塞的优点。
  • catch (bool, optional) :是否应该自动捕获接收器处理日志消息时发生的错误。如果True上显示异常消息 sys.stderr。但是,异常不会传播到调用者,从而防止应用程序崩溃。

如果当接收器(sink)是文件路径( pathlib.Path )时,可以应用下列参数,同时add() 会返回与所添加的接收器相关联的标识符:

  • rotation:分隔日志文件,何时关闭当前日志文件并启动一个新文件的条件,;例如,"500 MB"、"0.5 GB"、"1 month 2 weeks"、"10h"、"monthly"、"18:00"、"sunday"、"monday at 18:00"、"06:15"

  • retention (str, int, datetime.timedelta or callable, optional) ,可配置旧日志的最长保留时间,例如,"1 week, 3 days"、"2 months"

  • compression (str or callable, optional) :日志文件在关闭时应转换为的压缩或归档格式,例如,"gz"、"bz2"、"xz"、"lzma"、"tar"、"tar.gz"、"tar.bz2"、"tar.xz"、"zip"

  • delay (bool, optional):是否应该在配置了接收器之后立即创建文件,或者延迟到第一个记录的消息。默认为' False '。

  • mode (str, optional) :与内置open()函数一样的打开模式。默认为' "a"(以附加模式打开文件)。

  • buffering (int, optional) :内

    置open()函数的缓冲策略,它默认为1(行缓冲文件)。

  • encoding (str, optional) :文件编码与内置的' open() '函数相同。如果' None ',它默认为'locale.getpreferredencoding() 。

format (str or callable, optional) :格式化模块

属性

key Description
elapsed 从程序开始经过的时间差
exception 格式化异常(如果有),否则为' None '
extra 用户绑定的属性字典(参见bind())
file 进行日志记录调用的文件
function 进行日志记录调用的函数
level 用于记录消息的严重程度
line 源代码中的行号
message 记录的消息(尚未格式化)
module 进行日志记录调用的模块
name 进行日志记录调用的__name__
process 进行日志记录调用的进程名
thread 进行日志记录调用的线程名
time 发出日志调用时的可感知的本地时间

通过 extra bind() 添加额外属性来为结构化日志提供更多属性信息,如下:

from loguru import logger

def format_log():
    """

    Returns:

    """
    trace = logger.add('2021-3-28.log', format="{time:YYYY-MM-DD HH:mm:ss} {extra[ip]}  {extra[username]} {level} From {module}.{function} : {message}")
    
    extra_logger = logger.bind(ip="192.168.0.1", username="张三")
    extra_logger.info('This is info information')
    extra_logger.bind(username="李四").error("This is error information")

    extra_logger.warning('This is warn information')

if __name__ == '__main__':
    format_log()

如下,我们可以看到在 2021-3-28.log 日志文件中,看到日志按上述模板记录,如下:

2021-03-28 16:27:11 192.168.0.1  张三 INFO From 2021-3-28.format_log : This is info information
2021-03-28 16:27:11 192.168.0.1  李四 ERROR From 2021-3-28.format_log : This is error information
2021-03-28 16:27:11 192.168.0.1  张三 WARNING From 2021-3-28.format_log : This is warn information

level 配置日志最低日志级别

from loguru import logger

trace = logger.add('2021-3-29.log', level='ERROR')

rotation 配置日志滚动记录的机制

我们想周期性的创建日志文件,或者按照文件大小自动分隔日志文件,我们可以直接使用 add 方法的 rotation 参数进行配置。

例如,每 200MB 创建一个日志文件,避免每个 log 文件过大,如下:

from loguru import logger

trace = logger.add('2021-3-28.log', rotation="200 MB")

例如,每天6点 创建一个日志文件,如下:

from loguru import logger

trace = logger.add('2021-3-28.log', rotation='06:00')

例如,每隔2周创建一个 日志文件,如下:

from loguru import logger

trace = logger.add('2021-3-28.log', rotation='2 week')

retention 配置日志保留机制

通常,一些久远的日志文件,需要周期性的去清除,避免日志堆积,浪费存储空间。我们可以通过add方法的 retention 参数可以配置日志的最长保留时间。

例如,设置日志文件最长保留 7 天,如下:

from loguru import logger

trace = logger.add('2021-3-28.log', retention='7 days')

compression 配置日志压缩格式

loguru 还可以配置文件的压缩格式,比如使用 zip 文件格式保存,示例如下:

from loguru import logger

trace = logger.add('2021-3-28.log', compression='zip')

serialize 日志序列化

如果我们希望输出类似于Json-line格式的结构化日志,我们可以通过 serialize 参数,将日志信息序列化的json格式写入log 文件,最后可以将日志文件导入类似于

MongoDB、ElasticSearch 中用作后续的日志分析,代码示例如下:

from loguru import logger
import platform

trace= logger.add('2021-3-28.log', serialize=True)
logger.info('If you are using Python {version}, prefer {feature} of course!', version=platform.python_version(), feature='f-strings')
{
    "text": "2021-03-28 13:44:17.104 | INFO     | __main__:<module>:9 - If you are using Python 3.7.6, prefer f-strings of course!\n",
    "record": {
        "elapsed": {
            "repr": "0:00:00.010911",
            "seconds": 0.010911
        },
        "exception": null,
        "extra": {
            "version": "3.7.6",
            "feature": "f-strings"
        },
        "file": {
            "name": "2021-3-28.py",
            "path": "F:/code/MOC/2021-3-28.py"
        },
        "function": "<module>",
        "level": {
            "icon": "\u2139\ufe0f",
            "name": "INFO",
            "no": 20
        },
        "line": 9,
        "message": "If you are using Python 3.7.6, prefer f-strings of course!",
        "module": "2021-3-28",
        "name": "__main__",
        "process": {
            "id": 22604,
            "name": "MainProcess"
        },
        "thread": {
            "id": 25696,
            "name": "MainThread"
        },
        "time": {
            "repr": "2021-03-28 13:44:17.104522+08:00",
            "timestamp": 1616910257.104522
        }
    }
}

Traceback 记录(异常追溯)

对于日志而言,没有错误堆栈的日志是没有灵魂的。Loguru 允许显示整个堆栈信息来帮助你发现问题(包括变量)。

loguru集成了一个名为 better_exceptions 的库,不仅能够将异常和错误记录,并且还能对异常进行追溯,如下,我们通过数学运算来举例

通过catch装饰器的方式实现异常捕获,代码示例如下:

from loguru import logger

logger.add("2021-3-28.log", backtrace=True, diagnose=True)

def func(a, b):
    return a / b

@logger.catch
def nested(c):
    func(5, c)

nested(0)

运行上述代码,我们可以发现loguru输出的 Traceback 日志信息, Traceback 日志信息中同时输出了当时的变量值,同时也会出入到日志文件中,如下:

2021-11-11 12:53:37.125 | ERROR    | __main__:<module>:19 - An error has been caught in function '<module>', process 'MainProcess' (17236), thread 'MainThread' (12668):
Traceback (most recent call last):

> File "F:\mygits\123\11.py", line 19, in <module>
    nested(0)
    └ <function nested at 0x03A3E4F0>

  File "F:\mygits\123\11.py", line 16, in nested
    func(5, c)
    │       └ 0
    └ <function func at 0x01AB1D18>

  File "F:\mygits\123\11.py", line 11, in func
    return a / b
           │   └ 0
           └ 5

通过装饰器来对异常进行追溯,会有一个不太好的地方,就是自由度不够。他是将函数里面的所有异常都进行追溯。但是有时候我们只是想对某一块代码进行追溯。

这时我们就通过 logger.exception 来实现异常的捕获与记录。

logger.add("out.log", backtrace=True, diagnose=True)  # Caution, may leak sensitive data in prod

def func(a, b):
    return a / b

def nested(c):
    try:
        func(5, c)
    except ZeroDivisionError:
        logger.exception("What?!")

nested(0)

标签:log,loguru,28,logurn,2021,模块,日志,logger
来源: https://www.cnblogs.com/bkhb/p/16541393.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有