跳转至

loguru显示日志和写入日志

自定义日志显示和写入

loguru是一个比较简单的日志管理的模块,但是如果有时有这样的需求:程序同时有info、warning、error等日志需要写入到文本中,但是不是所有的日志都需要打印到终端中让用户看到,比如只让用户看到warning、error的日志信息,但是隐藏部分info的日志,这个时候可以使用以下的方法:

Python
from loguru import logger
import sys

class CustomLogger:
    def __init__(self) -> None:
        self.logger = logger
        logger.add("test.log")
        self.set_logger_filter()

    def stdout_filter(self, record):
        return record["level"].name in ("DEBUG", "INFO", "WARNING")

    def stderr_filter(self, record):
        return record["level"].name in ("ERROR", "CRITICAL")

    def write_filter(self, record):
        return record.get("extra").get("write") is True

    def set_logger_filter(self):
        # stdout_handler = {"sink": sys.stdout, "filter": self.stdout_filter}
        stderr_handler = {"sink": sys.stderr, "filter": self.stderr_filter}
        write_handler = {"sink": "test2.log", "filter": self.write_filter}
        self.logger.configure(handlers=[stderr_handler, write_handler])

    def get_logger(self):
        return self.logger


log = CustomLogger().get_logger()

log.bind(write=True).debug("This is a debug message")
log.bind(write=True).info("This is a info message")
log.info("This is a info message2")
log.bind(write=True).warning("This is a warning message")
log.bind(write=True).error("This is a error message")
log.bind(write=True).critical("This is a critical message")

这样终端中只会输出以下内容:

Bash
2023-11-17 16:20:09.664 | ERROR    | __main__:<module>:36 - This is a error message
2023-11-17 16:20:09.664 | CRITICAL | __main__:<module>:37 - This is a critical message

而在test.log中却会输出以下内容:

Text Only
2023-11-17 16:20:09.664 | DEBUG    | __main__:<module>:32 - This is a debug message
2023-11-17 16:20:09.664 | INFO     | __main__:<module>:33 - This is a info message
2023-11-17 16:20:09.664 | WARNING  | __main__:<module>:35 - This is a warning message
2023-11-17 16:20:09.664 | ERROR    | __main__:<module>:36 - This is a error message
2023-11-17 16:20:09.664 | CRITICAL | __main__:<module>:37 - This is a critical message

Note

第一个需要注意的是过滤日志的部分,也就是set_logger_filter这一块,这里需要提前定义好哪些日志需要显示到终端,哪些日志是写入到文件等,第二个是log.bind(write=True).critical等,如果假如了bind(),这样在logger的字典中会有一个extra参数,这个参数对外是看不到的,因此可以通过这个方法去进行过滤

自动捕获异常

有的时候我们不知道代码中哪里会存在一些错误导致程序崩溃,这个时候可以使用logger.catch()作为装饰器放在每个函数/方法的上一行,这样一旦某个方法/函数出现异常,loguru就会及时显示并写入到日志中,方便处理

其实cigitb也能实现,而且更简单,不过考虑到这个模块会在后续的python版本中被移除,而且能调的功能太少,就不考虑了,不过如果只是做简单的异常捕获,这个模块是相当简单的,网上资料有很多,可以自行搜索

添加logger.catch()注意事项

测试时原本想偷个懒给类增加一个logger.catch(),结果直接报错,只能给方法添加这个装饰器,所以就有些尴尬了