Python方便又强大的日志记录器——loguru

Posted 程序媛一枚~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python方便又强大的日志记录器——loguru相关的知识,希望对你有一定的参考价值。

Python方便又强大的日志记录器——loguru

Loguru是一个旨在使Python日志记录变得愉快的库。该库通过添加一系列有用的功能来解决标准记录器的警告,从而减少Python日志记录的痛苦。

日志记录对每个应用程序都是基本的,它简化了调试过程。在应用程序中使用日志应该是一种自动化,Loguru试图让它既愉快又强大。

优点:

  • loguru的核心是只有一个记录器,默认是stderr

  • 记录器只是一个接口,它将日志消息分派给已配置的处理程序。如何添加处理程序?如何设置日志格式?如何过滤邮件?如何设置级别? 答案:add()函数
    logger.add(sys.stderr, format=“time level message”, filter=“my_module”, level=“INFO”)

  • 取代默认的stderr处理程序,只需调用logger.remove()

  • 将日志记录到文件
    logger.add(“file_time.log”)
    logger.add(“file_1.log”, rotation=“500 MB”) # 文件过大时自动滚动
    logger.add(“file_2.log”, rotation=“12:00”) # 每天中午12:00创建新文件
    logger.add(“file_3.log”, rotation=“1 week”) # 超过一周,自动创建新文件
    logger.add(“file_X.log”, retention=“10 days”) # 一段时间10天后清除
    logger.add(“file_Y.log”, compression=“zip”) # 压缩节省空间
    logger.info(“If you’re using Python , prefer feature of course!”, 3.6, feature=“f-strings”) # 有比%更强大的格式化,占位符

  • 线程或主线程内异常捕获
    @logger.catch
    def my_function(x, y, z):
    return 1 / (x + y + z)

  • 用颜色记录日志
    logger.add(sys.stdout, colorize=True, format=“time message”)

  • 异步,进程安全,多线程安全的记录日志,通过排队的方式记录日志
    logger.add(“somefile.log”, enqueue=True)

  • 希望日志序列化以便于分析或传递:使用serialize参数,每个日志消息将在发送到配置的接收器之前转换为JSON字符串。
    logger.add(custom_sink_function, serialize=True)

  • 使用bind记录日志上下文
    logger.add(“file.log”, format=“extra[ip] extra[user] message”)
    context_logger = logger.bind(ip=“192.168.0.1”, user=“someone”)
    context_logger.info(“Contextualize your logger easily”)
    context_logger.bind(user=“someone_else”).info(“Inline binding of extra attribute”)
    context_logger.info(“Use kwargs to add context during formatting: user”, user=“anybody”)

  • 使用contextualize()临时修改上下文本地状态:

  • 通过结合bind()和filter,可以对日志进行更细粒度的控制:
    logger.add(“special.log”, filter=lambda record: “special” in record[“extra”])
    logger.debug(“This message is not logged to the file”)
    logger.bind(special=True).info(“This message, though, is logged to the file!”)

  • patch()方法允许动态值附加到每个新消息的记录dict
    logger.add(sys.stderr, format=“extra[utc] message”)
    logger = logger.patch(lambda record: record[“extra”].update(utc=datetime.utcnow()))

  • 希望在生产中记录详细信息而不降低性能,可以使用opt()方法来实现这一点
    logger.opt(lazy=True).debug(“If sink level <= DEBUG: x”, x=lambda: expensive_function(2 ** 64))

  • opt()有很多用途
    logger.opt(exception=True).info(“Error stacktrace added to the log message (tuple accepted too)”) # 错误堆栈跟踪添加到日志消息
    logger.opt(colors=True).info(“Per message colors”)
    logger.opt(record=True).info(“Display values from the record (eg. record[thread])”)
    logger.opt(raw=True).info(“Bypass sink formatting\\n”)
    logger.opt(depth=1).info(“Use parent stack context (useful within wrapped functions)”)
    logger.opt(capture=False).info(“Keyword arguments not added to dest dict”, dest=“extra”)

    new_level = logger.level(“SNAKY”, no=38, color=“”, icon=“🐍”)
    logger.log(“SNAKY”, “Here we go!”)

  • 更好的时间日期处理
    logger.add(“file.log”, format=“time:YYYY-MM-DD at HH:mm:ss | level | message”)

  • 脚本的日志记录器示例
    config =
    “handlers”: [
    “sink”: sys.stdout, “format”: “time - message”,
    “sink”: “file.log”, “serialize”: True,
    ],
    “extra”: “user”: “someone”

    logger.configure(**config)

  • 库的日志记录器
    logger.disable(“my_library”)
    logger.info(“No matter added sinks, this message is not displayed”)
    logger.enable(“my_library”)
    logger.info(“This message however is propagated to the sinks”)

  • 与标准日志库兼容:希望将内置日志处理程序用作Loguru接收器
    handler = logging.handlers.SysLogHandler(address=(‘localhost’, 514))
    logger.add(handler)

  • 拦截向Loguru接收器发送的标准日志消息

  • 详尽的通知者:Loguru可以很容易地与强大的通知程序库(必须单独安装)相结合,以便在程序意外失败时接收电子邮件或发送许多其他类型的通知。
    import notifiers

    params =
    “username”: “you@gmail.com”,
    “password”: “abc123”,
    “to”: “dest@gmail.com”

  • 发送一条单独提醒
    notifier = notifiers.get_notifier(“gmail”)
    notifier.notify(message=“The application is running!”, **params)

  • 每条错误消息一个提醒
    from notifiers.logging import NotificationHandler

    handler = NotificationHandler(“gmail”, defaults=params)
    logger.add(handler, level=“ERROR”)

  • 比内置日志记录快10倍
    尽管在大多数情况下,日志对性能的影响可以忽略不计,但零成本日志可以在任何地方使用它,而无需太多担心。
    在即将发布的版本中,Loguru的关键功能将以C语言实现,以实现最高速度。

源码

# loguru的核心是只有一个记录器,默认是stderr
import logging.handlers
import sys
from datetime import datetime

from loguru import logger

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

# 记录器只是一个接口,它将日志消息分派给已配置的处理程序。
# 如何添加处理程序?如何设置日志格式?如何过滤邮件?如何设置级别? 答案:add()函数。
logger.add(sys.stderr, format="time level message", filter="my_module", level="INFO")

# 取代默认的stderr处理程序,只需调用logger.remove()

# 将日志记录到文件
logger.add("file_time.log")

logger.add("file_1.log", rotation="500 MB")  # 文件过大时自动滚动
logger.add("file_2.log", rotation="12:00")  # 每天中午12:00创建新文件
logger.add("file_3.log", rotation="1 week")  # 超过一周,自动创建新文件
logger.add("file_X.log", retention="10 days")  # 一段时间10天后清除
logger.add("file_Y.log", compression="zip")  # 压缩节省空间

logger.info("If you're using Python , prefer feature of course!", 3.6, feature="f-strings")  # 有比%更强大的格式化,占位符


# 线程或主线程内异常捕获
@logger.catch
def my_function(x, y, z):
    # An error? It's caught anyway!
    return 1 / (x + y + z)


my_function(1, 0, 0, 0)

# 用颜色记录日志
logger.add(sys.stdout, colorize=True, format="<green>time</green> <level>message</level>")

# 异步,进程安全,多线程安全的记录日志,通过排队的方式记录日志
logger.add("somefile.log", enqueue=True)

logger.add("out.log", backtrace=True, diagnose=True)  # #注意,可能会泄漏敏感数据


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


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


nested(0)

# 希望日志序列化以便于分析或传递:使用serialize参数,每个日志消息将在发送到配置的接收器之前转换为JSON字符串。
# logger.add(custom_sink_function, serialize=True)

# 使用bind记录日志上下文
logger.add("file.log", format="extra[ip] extra[user] message")
context_logger = logger.bind(ip="192.168.0.1", user="someone")
context_logger.info("Contextualize your logger easily")
context_logger.bind(user="someone_else").info("Inline binding of extra attribute")
context_logger.info("Use kwargs to add context during formatting: user", user="anybody")

# 使用contextualize()临时修改上下文本地状态:
# with logger.contextualize(task=task_id):
#     do_something()
#     logger.info("End of task")

# 通过结合bind()和filter,可以对日志进行更细粒度的控制:
logger.add("special.log", filter=lambda record: "special" in record["extra"])
logger.debug("This message is not logged to the file")
logger.bind(special=True).info("This message, though, is logged to the file!")

# patch()方法允许动态值附加到每个新消息的记录dict
logger.add(sys.stderr, format="extra[utc] message")
logger = logger.patch(lambda record: record["extra"].update(utc=datetime.utcnow()))


def expensive_function(a):
    print(a)


# 希望在生产中记录详细信息而不降低性能,可以使用opt()方法来实现这一点
logger.opt(lazy=True).debug("If sink level <= DEBUG: x", x=lambda: expensive_function(2 ** 64))

# opt()有很多用途
logger.opt(exception=True).info("Error stacktrace added to the log message (tuple accepted too)")  # 错误堆栈跟踪添加到日志消息
logger.opt(colors=True).info("Per message <blue>colors</blue>")
logger.opt(record=True).info("Display values from the record (eg. record[thread])")
logger.opt(raw=True).info("Bypass sink formatting\\n")
logger.opt(depth=1).info("Use parent stack context (useful within wrapped functions)")
logger.opt(capture=False).info("Keyword arguments not added to dest dict", dest="extra")

new_level = logger.level("SNAKY", no=38, color="<yellow>", icon="🐍")
logger.log("SNAKY", "Here we go!")

# 更好的时间日期处理
logger.add("file.log", format="time:YYYY-MM-DD at HH:mm:ss | level | message")

# 脚本的日志记录器示例
config = 
    "handlers": [
        "sink": sys.stdout, "format": "time - message",
        "sink": "file.log", "serialize": True,
    ],
    "extra": "user": "someone"

logger.configure(**config)

# 库的日志记录器
logger.disable("my_library")
logger.info("No matter added sinks, this message is not displayed")
logger.enable("my_library")
logger.info("This message however is propagated to the sinks")

# 与标准日志库兼容:希望将内置日志处理程序用作Loguru接收器
handler = logging.handlers.SysLogHandler(address=('localhost', 514))
logger.add(handler)

# 拦截向Loguru接收器发送的标准日志消息
class PropagateHandler(logging.Handler):
    def emit(self, record):
        logging.getLogger(record.name).handle(record)

logger.add(PropagateHandler(), format="message")

class InterceptHandler(logging.Handler):
    def emit(self, record):
        # 获取loguru日志level 如果村存在的话
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = record.levelno

        # Find caller from where originated the logged message.
        frame, depth = sys._getframe(6), 6
        while frame and frame.f_code.co_filename == logging.__file__:
            frame = frame.f_back
            depth += 1

        logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())

logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)

# 详尽的通知者:Loguru可以很容易地与强大的通知程序库(必须单独安装)相结合,以便在程序意外失败时接收电子邮件或发送许多其他类型的通知。
import notifiers

params = 
    "username": "xxx@gmail.com",
    "password": "xxx",
    "to": "destxxx@gmail.com"


# 发送一条单独提醒
notifier = notifiers.get_notifier("gmail")
notifier.notify(message="The application is running!", **params)

# 每条错误消息一个提醒
from notifiers.logging import NotificationHandler

handler = NotificationHandler("gmail", defaults=params)
logger.add(handler, level="ERROR")

# 比内置日志记录快10倍
# 尽管在大多数情况下,日志对性能的影响可以忽略不计,但零成本日志可以在任何地方使用它,而无需太多担心。
# 在即将发布的版本中,Loguru的关键功能将以C语言实现,以实现最高速度。

参考

以上是关于Python方便又强大的日志记录器——loguru的主要内容,如果未能解决你的问题,请参考以下文章

Loguru:Python 日志终极解决方案

『Python』优雅的记录日志——loguru

对 loguru 日志模块的错误日志自动发邮件

Python3 - Loguru 相见恨晚的输出日志工具

Python3 - Loguru 相见恨晚的输出日志工具

Python3 - Loguru 相见恨晚的输出日志工具