Python中的日志管理模块可以使用自带的logging,也可使用第三方Loguru模块,使用logging需要配置Handler、Formatter 进行一些处理,配置比较繁琐,而使用Loguru则较为简单。

安装

pip install loguru

基本使用

from loguru import logger

logger.info("this is a test info")
logger.debug("this is a debug message ")
logger.error("this is a error message ")

从loguru账号引入logger后,直接调用其 info,debug,error 方法即可。在 loguru 里面有且仅有一个主要对象,那就是 logger,loguru 里面有且仅有一个 logger,而且它已经被提前配置了一些基础信息,比如比较友好的格式化、文本颜色信息等等。上面的代码运行结果如下:

2021-04-27 17:30:13.308 | INFO     | __main__:<module>:10 - this is a test info
2021-04-27 17:30:13.309 | DEBUG    | __main__:<module>:11 - this is a debug message 
2021-04-27 17:30:13.309 | ERROR    | __main__:<module>:12 - this is a error message

可以看到其默认的输出格式是上面的内容,有时间、级别、模块名、行号以及日志信息,不需要手动创建 logger,直接使用即可。上面的日志信息是直接输出在控制台的,如果想要输出到其他的位置,比如存为文件,我们只需要使用一行代码声明即可。例如将结果同时输出到一个 runtime.log 文件里面,可以这么写:

from loguru import logger

logger.add("runtime.log")
logger.info("this is a test info")
logger.debug("this is a debug message ")
logger.error("this is a error message ")

详细使用

loguru 对输出到文件的配置有非常强大的支持,比如支持输出到多个文件,分级别分别输出,过大创建新文件,过久自动删除等等。add 方法定义:

def add(
        self,
        sink,
        *,
        level=_defaults.LOGURU_LEVEL,
        format=_defaults.LOGURU_FORMAT,
        filter=_defaults.LOGURU_FILTER,
        colorize=_defaults.LOGURU_COLORIZE,
        serialize=_defaults.LOGURU_SERIALIZE,
        backtrace=_defaults.LOGURU_BACKTRACE,
        diagnose=_defaults.LOGURU_DIAGNOSE,
        enqueue=_defaults.LOGURU_ENQUEUE,
        catch=_defaults.LOGURU_CATCH,
        **kwargs
    ):
    pass

skin参数可以传入多种不同的数据结构,如下:

  1. sink 可以传入一个 file 对象,例如 sys.stderr 或者 open('file.log', 'w') 都可以。
  2. sink 可以直接传入一个 str 字符串或者 pathlib.Path 对象,其实就是代表文件路径的,如果识别到是这种类型,它会自动创建对应路径的日志文件并将日志输出进去。
  3. sink 可以是一个方法,可以自行定义输出实现。
  4. sink 可以是一个 logging 模块的 Handler,比如 FileHandler、StreamHandler 等等,或者上文中我们提到的 CMRESHandler 照样也是可以的,这样就可以实现自定义 Handler 的配置。
  5. sink 还可以是一个自定义的类,具体的实现规范可以参见官方文档。

基本参数

其他参数例如 format、filter、level 等等。其实它们的概念和格式和 logging 模块都是基本一样的了,例如这里使用 format、filter、level 来规定输出的格式:

logger.add('runtime.log', format="{time} {level} {message}", filter="my_module", level="INFO")

删除skin

添加 sink 之后可以对其进行删除,相当于重新刷新并写入新的内容。删除的时候根据刚刚 add 方法返回的 id 进行删除即可,看下面的例子:

from loguru import logger

trace = logger.add('runtime.log')
logger.debug('this is a debug message')
logger.remove(trace)
logger.debug('this is another debug message')

控制台输出:

2021-04-27 17:56:29.254 | DEBUG    | __main__:<module>:11 - this is a debug message
2021-04-27 17:56:29.254 | DEBUG    | __main__:<module>:13 - this is another debug message

日志文件 runtime.log 内容如下:

2021-04-27 17:56:29.254 | DEBUG    | __main__:<module>:13 - this is another debug message

可以发现,在调用 remove 方法之后,确实将历史 log 删除了。但实际上这并不是删除,只不过是将 sink 对象移除之后,在这之前的内容不会再输出到日志中。这样就可以实现日志的刷新重新写入操作。

rotation 配置

用了 loguru 可以非常方便地使用 rotation 配置,比如想一天输出一个日志文件,或者文件太大了自动分隔日志文件,可以直接使用 add 方法的 rotation 参数进行配置。

logger.add('runtime_{time}.log', rotation="500 MB")  # log文件超过500M时会新建一个log文件

使用 rotation 参数实现定时创建 log 文件

logger.add('runtime_{time}.log', rotation='00:00') # 每天0点新建一个log文件

retention 配置

retention 这个参数可以配置日志的最长保留时间。

logger.add('runtime.log', retention='10 days') # 保留最新10天的log

compression 配置

配置文件的压缩格式

logger.add('runtime.log', compression='zip') # 使用zip文件格式保存

字符串格式化

logger.info('If you are using Python {}, prefer {feature} of course!', 3.6, feature='f-strings')

Traceback 记录

使用装饰器 @logger.catch 可以在日志里记录 Traceback 信息

@logger.catch
def my_function(x, y, z):
    # An error? It's caught anyway!
    return 1 / (x + y + z)