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
-