python-28-日志模块Loguru的应用

参考为什么不推荐使用Python原生日志库?
参考loguru,一个神奇的 python 库
Loguru 是一个旨在为 Python 带来愉快的日志记录的库,它可以完全增强你的日志记录体验,并且非常易于使用。
对logging及Loguru进行使用对比。

1 Loguru的使用

1.1 将调试日志输出到终端

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

1.2 将日志输出到文件中

from loguru import logger
logger.add("file_{time}.log")
logger.debug("That's it, beautiful and simple logging!")

这将在当前运行的文件夹中生成 file_current time.log 的日志文件。
同时如果在IDE中执行,终端也会输出日志信息。

1.3 按时间滚动日志

要按时间滚动,只需要在 logger.add 参数中添加一个 rotation 参数即可。

from loguru import logger
# Create new file at 12AM
logger.add("file_2.log", rotation="12:00") 
logger.debug("That's it, beautiful and simple logging!")

这样,如果当前时间超过了这个设定的时间,就会生成一个新的日志文件。如果没有,请使用原始日志文件。

1.4 按大小滚动日志

from loguru import logger
logger.add("file_1.log", rotation="1 MB")
logger.debug("That's it, beautiful and simple logging!")

这样,一旦日志文件大小超过1MB,就会生成一个新的日志文件。

1.5 压缩日志

如果你不想删除原来的日志文件,Loguru 还支持直接压缩日志。

from loguru import logger
logger.add("file_2.log", compression="zip")

会直接将该日志文件压缩为zip。

1.6 定制颜色

Loguru 支持自定义颜色,如果你不喜欢它的默认颜色,你可以这样更改。

from loguru import logger
import sys
logger.add(sys.stdout,
           colorize=True,
           format="<black>{time}</black> <level>{message}</level>")
logger.debug("That's it, beautiful and simple logging!")

1.7 多进程安全

Loguru 默认是线程安全的,但它不是多进程安全的。
但如果你需要多进程/异步日志记录,它也支持,只需添加一个 enqueue 参数即可。
在config中配置全局的logger,这样主程序和子程序都会写入同一个日志文件中。
一、config.py

from loguru import logger
logger.add("file.log",enqueue=True)

二、main.py

from multiprocessing import Process
import os
from config import logger
from demo import fun
if __name__ == '__main__':
    # p进程执行fun函数
    p1 = Process(target=fun)
    p1.start()  # 进程开始
    logger.info("PID={},This is mainFun results".format(os.getpid()))
    p2 = Process(target=fun)
    p2.start()  # 进程开始

三、demo.py

import time
from config import logger
import os
def fun():
    count = 0
    while count < 30:
        logger.error("PID={},error message".format(os.getpid()))
        time.sleep(20)
        count = count + 1

2 logging与Loguru对比

2.1 快速示例

(1)在logging中,默认的日志功能输出的信息较为有限。
(2)看看loguru,默认生成的信息就较为丰富了,提供了执行时间、等级、在哪个函数调用、具体哪一行等信息。

2.1.1 logging

import logging

logger = logging.getLogger(__name__)

def main():
    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")

if __name__ == "__main__":
    main()

输出如下:

This is a warning message
This is an error message
输出(logging默认日志等级为warning,故此处未输出info与debug等级的信息)

2.1.2 Loguru

from loguru import logger

def main():
    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")

if __name__ == "__main__":
    main()

输出如下:
在这里插入图片描述
提供了执行时间、等级、在哪个函数调用、具体哪一行等信息。

2. 2 格式化日志

(1)在logging中使用%达到格式化目的。
(2)loguru使用和f-string相同的{}格式,更方便。

2.2.1 logging

import logging

# Create a logger and set the logging level
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

logger = logging.getLogger(__name__)

def main():
    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")

if __name__ == "__main__":
    main()

在这里插入图片描述

2.2.2 Loguru

from loguru import logger
import sys
logger.add(
    sys.stdout,
    level="INFO",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}",
)
def main():
    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")

if __name__ == "__main__":
    main()

控制台输出自定义格式的内容。
同时控制台输出默认格式的内容。
在这里插入图片描述

2.3 日志保存

(1)在logging中,实现日志保存与日志打印需要两个额外的类,FileHandler 和 StreamHandler。
(2)在loguru中,只需要使用add方法即可达到目的。

2.3.1 logging

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
    handlers=[
        logging.FileHandler(filename="info.log"),
        logging.StreamHandler(),
    ],
)

logger = logging.getLogger(__name__)

def main():
    logging.debug("This is a debug message")
    logging.info("This is an info message")
    logging.warning("This is a warning message")
    logging.error("This is an error message")


if __name__ == "__main__":
    main()

在这里插入图片描述

2.3.2 Loguru

from loguru import logger

logger.add(
    'info.log',
    format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}",
    level="INFO",
)


def main():
    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")


if __name__ == "__main__":
    main()

控制台会继续按debug级别输出。
日志文件中按info输出。
在这里插入图片描述

2.4 日志轮换

日志轮换指通过定期创建新的日志文件并归档或删除旧的日志来防止日志变得过大。
(1)在logging中,需要一个名为 TimedRotatingFileHandler 的附加类。
(2)在loguru中,可以通过将 rotation 和 retention 参数添加到 add 方法来达到目的。

2.4.1 logging

以下代码示例代表每周切换到一个新的日志文件 ( when=“S”, interval=10 ),并保留最多 4个日志文件 ( backupCount=4 )

import logging
from logging.handlers import TimedRotatingFileHandler

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# Create a formatter with the desired log format
formatter = logging.Formatter(
    "%(asctime)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

file_handler = TimedRotatingFileHandler(
    filename="debug2.log", when="S", interval=10, backupCount=4
)
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)


def main():
    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")


if __name__ == "__main__":
    main()

2.4.2 Loguru

from loguru import logger

logger.add("debug.log", level="INFO", rotation="10 seconds", retention="40 seconds")


def main():
    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")


if __name__ == "__main__":
    main()

2.5 日志筛选log filter

日志筛选指根据特定条件有选择的控制应输出与保存哪些日志信息。
(1)在logging中,实现该功能需要创建自定义日志过滤器类。
(2)在loguru中,可以简单地使用lambda函数来过滤日志。

2.5.1 logging

import logging


logging.basicConfig(
    filename="test.log",
    format="%(asctime)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    level=logging.INFO,
)


class CustomFilter(logging.Filter):
    def filter(self, record):
        return "my concern message" in record.msg


# Create a custom logging filter
custom_filter = CustomFilter()

# Get the root logger and add the custom filter to it
logger = logging.getLogger()
logger.addFilter(custom_filter)


def main():
    logger.info("my concern message")
    logger.info("Ha Ha")
    logger.info("my concern message continue")


if __name__ == "__main__":
    main()

2.5.2 Loguru

在loguru中,可以简单地使用lambda函数来过滤日志。

from loguru import logger

logger.add("test.log",
           filter=lambda x: "Cai Xukong" in x["message"],
           level="INFO")


def main():
    logger.info("my concern message")
    logger.info("Ha Ha")
    logger.info("my concern message continue")


if __name__ == "__main__":
    main()

2.6 捕获异常catching exception

(1)在logging中捕获异常较为不便且难以调试。
(2)在loguru中,通过显示包含变量值的完整堆栈跟踪来方便用户识别。

2.6.1 logging

import logging

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)


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


def nested(num):
    try:
        division(1, num)
    except ZeroDivisionError:
        logging.exception("ZeroDivisionError")


if __name__ == "__main__":
    nested(0)

输出如下:下面输出的信息未提供触发异常的num值信息。
在这里插入图片描述

2.6.2 Loguru

from loguru import logger


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

def nested(num):
    try:
        division(1, num)
    except ZeroDivisionError:
        logger.exception("ZeroDivisionError")


if __name__ == "__main__":
    nested(0)

在这里插入图片描述
值得一提的是,loguru中的catch装饰器允许用户捕获函数内任何错误,且还会标识发生错误的线程。

from loguru import logger


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


@logger.catch
def nested(num):
    division(1, num)


if __name__ == "__main__":
    nested(0)

在这里插入图片描述

Python Loguru 是一个易于使用的日志库,它提供了简洁的语法和强大的功能,可以帮助开发者在应用程序中记录和管理日志Loguru 具有以下特点: 1. 简洁的语法:Loguru 提供了简单直观的 API,使得记录日志变得轻而易举。开发者可以使用类似于 print 函数的语法来记录日志,而无需担心繁琐的配置。 2. 强大的功能:Loguru 支持将日志输出到控制台、文件、网络和其他自定义目标。开发者可以根据自己的需求配置不同的输出方式和格式。 3. 自动回滚:Loguru 具备自动回滚功能,可以根据配置的大小或时间进行日志文件的分割和归档,避免日志文件过大或过长。 4. 异常追踪:Loguru 提供了异常追踪功能,可以方便地记录和追踪应用程序中的异常信息,帮助开发者快速定位和修复问题。 5. 上下文管理:Loguru 支持上下文管理,可以在日志中添加上下文信息,如请求 ID、用户 ID 等,方便开发者跟踪和调试应用程序。 使用 Loguru 非常简单,只需要在代码中导入 loguru 模块,并使用 loguru.logloguru.logger 对象来记录日志即可。 下面是一个使用 Loguru 记录日志的示例: ```python import loguru loguru.logger.add("file.log") # 将日志输出到文件 loguru.logger.info("This is an info message") # 记录一条信息日志 loguru.logger.warning("This is a warning message") # 记录一条警告日志 loguru.logger.error("This is an error message") # 记录一条错误日志 ``` 以上是 Loguru 的一些基本用法,你还可以通过配置文件或函数参数来自定义日志记录的行为。详细的用法和更多功能请参考 Loguru 官方文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮皮冰燃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值