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 notifiersparams =
“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 NotificationHandlerhandler = 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的主要内容,如果未能解决你的问题,请参考以下文章