目录
- 基本使用
- format、filter、level
- 删除 sink
- rotation 配置
- compression 配置
- enqueue异步
- serialize序列化
- Traceback
摘要
loguru是 python 的一个第三方的日志记录包
项目地址 github: https://github.com/Delgan/loguru
文档:https://loguru.readthedocs.io/en/stable/index.html
安装
pip install loguru
简单使用
在 loguru
里面有且仅有一个主要对象,那就是 logger
from loguru import logger
logger.debug('this is a debug message')
logger.info('this is another debug message')
logger.warning('this is another debug message')
logger.error('this is another debug message')
logger.info('this is another debug message')
logger.success('this is success message!')
logger.critical('this is critical message!')
其默认的输出格式是有时间、级别、模块名、行号以及日志信息,不需要手动创建 logger
,直接使用即可,另外其输出还是彩色的,看起来会更加友好。
配置使用
loguru 对输出到文件的配置有非常强大的支持,比如支持输出到多个文件,分级别分别输出,过大创建新文件,过久自动删除等等
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,
rotation=None
retention=None
compression=None
catch=_defaults.LOGURU_CATCH,
**kwargs
):
pass
sink
可以传入不同的数据结构
sink
可以传入一个file
对象,例如sys.stderr
或者open('file.log', 'w')
都可以。sink
可以直接传入一个str 字符串
或者pathlib.Path
对象,其实就是代表文件路径的,如果识别到是这种类型,它会自动创建对应路径的日志文件并将日志输出进去。sink
可以是一个方法,可以自行定义输出实现。sink
可以是一个logging
模块的Handler
,比如FileHandler、StreamHandler
等等,或者上文中我们提到的CMRESHandler
照样也是可以的,这样就可以实现自定义 Handler 的配置。- sink 还可以是一个自定义的类,具体的实现规范可以参见官方文档。
基本使用
logger.add('runtime.log', format="{time} {level} {message}", level="INFO")
logger.debug('this is a debug message')
logger.info('this is another debug message')
logger.warning('this is another debug message')
logger.error('this is another debug message')
logger.info('this is another debug message')
logger.success('this is success message!')
logger.critical('this is critical message!')
输出到runtime.log
中为:
2021-09-12T20:05:20.148300+0800 INFO this is another debug message
2021-09-12T20:05:20.149300+0800 WARNING this is another debug message
2021-09-12T20:05:20.149300+0800 ERROR this is another debug message
2021-09-12T20:05:20.149300+0800 INFO this is another debug message
2021-09-12T20:05:20.149300+0800 SUCCESS this is success message!
2021-09-12T20:05:20.149300+0800 CRITICAL this is critical message!
format、filter、level
logger.add('runtime.log', format="{time} {level} {message}", filter="my_module", level="INFO")
#时间格式化
logger.add("file-{time}.log", format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}")
- 第一个参数是保存日志信息的文件路径,在后缀多了个
{time}
,就是获取当前时间节点,这样就会自动创建新的日志,支持自定义时间 - 当你需要输出中文日志的时候,请加上
encoding="utf-8"
,避免出现乱码 enqueue=True
代表异步写入,在多进程同时往日志文件写日志的时候使用队列达到异步功效rotation
可以理解成日志的创建时机,可以有多种写法
- rotation="500 MB" :当日志文件达到500MB时就会重新生成一个文件
- rotation="12:00" :每天12点就会创建新的文件、
- rotation="1 week" :每隔一周创建一个log
retention
配置日志的最长保留时间,官方例子: "1 week, 3 days"、"2 months"compression
配置文件的压缩格式,可以配置常见的格式 zip、tar、gz、tar.gz 等
删除 sink
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')
在调用 remove 方法之后,确实将历史 log 删除
控制台输出如下:
2019-10-13 23:18:26.469 | DEBUG | __main__:<module>:4 - this is a debug message
2019-10-13 23:18:26.469 | DEBUG | __main__:<module>:6 - this is another debug message
日志文件 runtime.log 内容如下:
2019-10-13 23:18:26.469 | DEBUG | __main__:<module>:4 - this is a debug message
rotation 配置
每 500MB 存储一个文件,每个 log 文件过大就会新创建一个 log 文件。我们在配置 log 名字时加上了一个 time 占位符,这样在生成时可以自动将时间替换进去,生成一个文件名包含时间的 log 文件
实现定时创建 log 文件
每隔一周创建一个 log 文件
设置日志文件最长保留 10 天
logger.add('runtime_{time}.log', rotation="500 MB")
logger.add('runtime_{time}.log', rotation='00:00')
logger.add('runtime_{time}.log', rotation='1 week')
logger.add('runtime.log', retention='10 days')
compression 配置
配置文件的压缩格式,比如使用 zip 文件格式保存
logger.add('runtime.log', compression='zip')
可选格式为"gz", "bz2", "xz", "lzma", "tar", "tar.gz", "tar.bz2",
"tar.xz", "zip"
enqueue异步
要记录的消息是否应该在到达接收器之前首先通过一个多进程安全的队列。这在通过多个进程记录文件时非常有用。
logger.add("somefile.log", enqueue=True) # 异步写入
serialize序列化
logger.add("somefile.log", serialize=True) # 序列化为json
Traceback
提供的装饰器就可以直接进行 Traceback 的记录
catch.
def my_function(x, y, z):
# An error? It's caught anyway!
return 1 / (x + y + z)
my_function(0, 0, 0)
# 运行完毕之后,可以发现 log 里面就出现了 Traceback 信息
> File "run.py", line 15, in <module>
my_function(0, 0, 0)
└ <function my_function at 0x1171dd510>
File "/private/var/py/logurutest/demo5.py", line 13, in my_function
return 1 / (x + y + z)
│ │ └ 0
│ └ 0
└ 0
ZeroDivisionError: division by zero
loguru封装类
"""
操作日志记录
"""
import time
from loguru import logger
from pathlib import Path
project_path = Path.cwd().parent
log_path = Path(project_path, "log")
t = time.strftime("%Y_%m_%d")
class Loggings:
__instance = None
logger.add(f"{log_path}/interface_log_{t}.log", rotation="500MB", encoding="utf-8", enqueue=True,
retention="10 days")
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = super(Loggings, cls).__new__(cls, *args, **kwargs)
return cls.__instance
def info(self, msg):
return logger.info(msg)
def debug(self, msg):
return logger.debug(msg)
def warning(self, msg):
return logger.warning(msg)
def error(self, msg):
return logger.error(msg)
loggings = Loggings()
if __name__ == '__main__':
loggings.info("中文test")
loggings.debug("中文test")
loggings.warning("中文test")
loggings.error("中文test")
logger.info('If you are using Python {}, prefer {feature} of course!', 3.6, feature='f-strings')
n1 = "cool"
n2 = [1, 2, 3]
logger.info(f'If you are using Python {n1}, prefer {n2} of course!')