python自带的logging模块,需要完成复杂的配置才能很好的使用,基本生产环境都需要进行二次包装。
loguru专门梳理了这方面的问题,可以通过简单直接的配置完成你的需求。
简单的例子:
from loguru import logger
logger.info("hello from loguru")
输出到标准输出:
2023-09-10 09:38:52.275 | INFO | __main__:<module>:2 - hello from loguru
输出到日志文件:
from loguru import logger
logger.remove(0)
logger.add("out.log")
logger.success("Written message to log file")
pip install loguru
最简单的使用:
from loguru import logger
# 在标准输出里面输出一行debug日志
logger.debug("That's it, beautiful and simple logging!")
loguru提供了七层日志层级,或者说七种日志类型。
生产环境中,常常在不同场景下使用不用的日志类型,用于处理各种问题。
每种类型的日志有一个整数值,表示日志层级,我们成为log level no。
logger.trace("A trace message.")
logger.debug("A debug message.")
logger.info("An info message.")
logger.success("A success message.")
logger.warning("A warning message.")
logger.error("An error message.")
logger.critical("A critical message.")
输出如下:
2022-08-10 11:58:33.224 | DEBUG | __main__:<module>:12 - A debug message.
2022-08-10 11:58:33.224 | INFO | __main__:<module>:13 - An info message.
2022-08-10 11:58:33.225 | SUCCESS | __main__:<module>:14 - A success message.
2022-08-10 11:58:33.226 | WARNING | __main__:<module>:15 - A warning message.
2022-08-10 11:58:33.226 | ERROR | __main__:<module>:16 - An error message.
2022-08-10 11:58:33.227 | CRITICAL | __main__:<module>:17 - A critical message.
如果你在linux的终端上,可以看到不同类型的日志,已经有不同的颜色加以区分,默认的配置已经很方便的让我们识别和使用了。
请注意,上述输出不包括TRACE级别的日志信息。这是因为Loguru默认使用DEBUG作为其最低日志级别,导致任何严重性低于DEBUG的日志信息都会被忽略。
如果您想更改默认级别,可以使用下面所示的add()方法的级别参数:
import sys
from loguru import logger
logger.remove(0)
logger.add(sys.stderr, level="INFO")
remove()方法被首先调用,以删除默认处理程序的配置(其ID为0)。然后,add()方法向记录器添加一个新处理程序。该处理程序将记录到标准错误,只记录INFO或更高级别的日志。
在日常使用中,如果默认的输出内容不够,我们还可以自定义日志的输出内容和格式。
可以通过add()方法中的格式选项对Loguru生成的日志记录进行重新格式化。
Loguru 中的每条日志记录都是一个 Python 字典,其中包含其时间戳、日志级别等数据。
可以使用loguru提供的格式化指令,包括或重新排列每条信息,如下所示:
import sys
from loguru import logger
logger.remove(0)
logger.add(sys.stderr, format="{time} | {level} | {message}")
logger.debug("Happy logging with Loguru!")
格式参数定义了自定义格式,在这个例子中有三个指令:
{time}:时间戳
{level}:日志级别
{message}:日志消息
输出如下:
2022-08-10T15:01:32.154035-0400 | DEBUG | Happy logging with Loguru!
Loguru还通过其序列化选项支持JSON格式的结构化日志。
这可以让你以JSON格式输出你的日志,这样机器可以很容易地解析和分析它,因为每条记录中的信息将以键/值对的形式提供。
import sys
from loguru import logger
logger.remove(0)
logger.add(sys.stderr, format="{time:MMMM D, YYYY > HH:mm:ss!UTC} | {level} | {message}", serialize=True)
logger.debug("Happy logging with Loguru!")
json格式的输出:
{"text": "August 10, 2022 > 19:38:06 | DEBUG | Happy logging with Loguru!\n", "record": {"elapsed": {"repr": "0:00:00.004000", "seconds": 0.004}, "exception": null, "extra": {}, "file": {"name": "app.py", "path": "C:\\Users\\Eric\\Documents\\Better Stack\\loguru-demo\\app.py"}, "function": "<module>", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 8, "message": "Happy logging with Loguru!", "module": "app", "name": "__main__", "process": {"id": 22652, "name": "MainProcess"}, "thread": {"id": 25892, "name": "MainThread"}, "time": {"repr": "2022-08-10 15:38:06.369578-04:00", "timestamp": 1660160286.369578}}}
最简单的配置如下:
logger.add("loguru.log")
logger.debug("A debug message.")
输出如下:
cat loguru.log
2022-08-11 13:16:52.573 | DEBUG | __main__:<module>:13 - A debug message.
当add函数配置为一个文件时,add方法提供了更多选项来自定义日志文件的处理方式:
# 将自动删除超过一分钟的老文件
logger.add("loguru.log", rotation="5 seconds", retention="1 minute")
# 将仅保留三个最新文件
logger.add("loguru.log", rotation="5 seconds", retention=3)
一个完整的配置:
logger.add(
sink="./logs/app.log",
enqueue=True,
rotation="4 weeks",
retention="4 months",
encoding="utf-8",
backtrace=True,
diagnose=True,
compression="zip",
)
add函数参数的完整解释:
在上面的配置中,我们讲到,可以使用add函数来配置最小的日志级别,如果我们需要把不同的日志输出到不同的文件中,我们需要使用到filter参数:
import sys
from loguru import logger
def level_filter(level):
def is_level(record):
return record["level"].name == level
return is_level
logger.remove(0)
logger.add("./logs/app.log", filter=level_filter(level="WARNING"))
输出如下:
2022-09-30 12:17:00.548 | WARNING | __main__:<module>:15 - A warning message.
还可以使用lambda函数直接配置filter参数,一个完整的例子:
from loguru import logger
# 设置不同级别的日志输出文件
logger.add("debug.log", level="DEBUG", rotation="10 MB", filter=lambda record: record["level"].name == "DEBUG")
logger.add("info.log", level="INFO", rotation="10 MB", filter=lambda record: record["level"].name == "INFO")
logger.add("warning.log", level="WARNING", rotation="10 MB", filter=lambda record: record["level"].name == "WARNING")
logger.add("error.log", level="ERROR", rotation="10 MB", filter=lambda record: record["level"].name == "ERROR")
logger.add("critical.log", level="CRITICAL", rotation="10 MB", filter=lambda record: record["level"].name == "CRITICAL")
# 输出不同级别的日志消息
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")
logger.critical("This is a critical message")
loguru提供了非常方便的异常定位功能,可以直接使用catch闭包,把抛出异常的位置记录到日志中。
from loguru import logger
logger.add(sink='log.log')
@logger.catch
def my_function(x, y, z):
return 1 / (x + y + z)
res = my_function(0,0,0)
输出如下:
> File "/var/folders/kb/0pw_yx2n75z8mlyzjk3mwlwc0000gn/T/ipykernel_85315/1609034425.py", line 9, in <module>
res = my_function(0,0,0)
└ <function my_function at 0x7fcce2170670>
File "/var/folders/kb/0pw_yx2n75z8mlyzjk3mwlwc0000gn/T/ipykernel_85315/1609034425.py", line 7, in my_function
return 1 / (x + y + z)
│ │ └ 0
│ └ 0
└ 0
ZeroDivisionError: division by zero