Validus A dead simple Python data validation library.…
Python: 日志记录方案 loguru, 日志模块, loguru模块, logger日志


loguru:是一个 Python 简易日志库,该库旨在通过添加一系列有用的功能来解决标准记录器的注意事项,从而减少 Python 日志记录的痛苦。
GitHub 地址:github.com/Delgan/loguru
前言
keep it simple , keep it stupid . loguru模块大概是符合这一精神的,其让你把精力从一些日志的调配的琐碎事情上抽离出来,好让你有更多的精力去解决核心问题。基本上使用过之后,就好像使用了python的新特性 f-string
一样,you just can not stop to use it. 你会忍不住想要使用它。
就最简单的使用:
from loguru import logger
接触过logging的马上就知道这个logger是个什么东西了,然后就想通常那样 logger.info('what')
之类的去打日志即可。默认的logger的日志格式就已经非常好了。
通常这个就已经够用了,实际上容器化了的应用或者某些应用场景,是要求你的日志都打印在默认终端上的,还有某些专门管理日志的工具,也要求你的应用就打印在默认终端。
某些情况下你可能需要将日志同时打印到文件中:
logger.add('<filename>.log')
此外还支持这样带时间戳的文件名:
logger.add('file_{time}.log')
文件控制更高级的用法如下:
logger.add("file_1.log", rotation="500 MB") # 文件过大自动开启新的日志文件
logger.add("file_2.log", rotation="12:00") # 每天12:00 开启新的文件
logger.add("file_3.log", rotation="1 week") # 一周的时间之后开启新的文件
logger.add("file_X.log", retention="10 days") # 10天之后清除旧日志
logger.add("file_Y.log", compression="zip") # 压缩日志
loguru还有很多高级用法,这个以后再看,现在最关键的一个问题是如何兼容别的logger,比如说tornado或者django有一些默认的logger。
经过研究,最好的解决方案是参考官方文档的,完全整合logging的工作方式。比如下面将所有的logging都用loguru的logger再发送一遍消息。
class InterceptHandler(logging.Handler): def emit(self, record): # Retrieve context where the logging call occurred, this happens to be in the 6th frame upward logger_opt = logger.opt(depth=6, exception=record.exc_info) logger_opt.log(record.levelno, record.getMessage()) logging.basicConfig(handlers=[InterceptHandler()], level=0)
这个 depth=6
大有讲究,似乎只有设置为6才能正确追踪原日志代码所在地,因为我们是日志信号再发送了的。
然后上面的 record.levelno
我发现可能换成 record.levelname
也是不错的。
这样原logging的日志流就和loguru整合起来了。
解决中文乱码问题
项目地址 github: https://github.com/Delgan/loguru
文档:https://loguru.readthedocs.io/en/stable/index.html
安装
pip install loguru
1、输出日志
from loguru import logger logger.debug("这是一条debug日志")
终端执行后出现带颜色的日志,挺酷的

2、输出到文件
from loguru import logger logger.add("file_{time}.log") logger.debug("这是一条debug日志") logger.info("这是一条info日志")
目录下多出一个日志文件 :file_2019-03-14_19-53-25_661314.log

3、日志规则
设置日志格式,过滤器,日志级别
from loguru import logger logger.add("file.log", format="{time} {level} {message}", filter="", level="INFO") logger.debug("这是一条debug日志") logger.info("这是一条info日志")
from loguru import logger logger.add('logs/z_project.log', level='DEBUG', format='{time:YYYY-MM-DD :mm:ss} - {level} - {file} - {line} - {message}', rotation="10 MB") logger.info('可以写日志了')
输出
2019-03-14T20:01:25.392454+0800 INFO 这是一条info日志
4、日志文件
文件管理方式
logger.add("file_1.log", rotation="500 MB") # 文件过大就会重新生成一个文件 logger.add("file_2.log", rotation="12:00") # 每天12点创建新文件 logger.add("file_3.log", rotation="1 week") # 文件时间过长就会创建新文件 logger.add("file_X.log", retention="10 days") # 一段时间后会清空 logger.add("file_Y.log", compression="zip") # 保存zip格式
5、其他参数
logger.add("somefile.log", enqueue=True) # 异步写入 logger.add("somefile.log", serialize=True) # 序列化为json
6、时间格式化
logger.add("file.log", format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}")
配合notifiers模块
github: https://github.com/notifiers/notifiers
文档:https://notifiers.readthedocs.io/en/latest/
7、在工程中创建多个文件处理器对象并解决中文乱码问题
# coding=utf-8 import os import sys from loguru import logger BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) log_file_path = os.path.join(BASE_DIR, 'Log/my.log') err_log_file_path = os.path.join(BASE_DIR, 'Log/err.log') logger.add(sys.stderr, format="{time} {level} {message}", filter="my_module", level="INFO") # logger.add(s) logger.add(log_file_path, rotation="500 MB", encoding='utf-8') # Automatically rotate too big file logger.add(err_log_file_path, rotation="500 MB", encoding='utf-8', level='ERROR') # Automatically rotate too big file logger.debug("That's it, beautiful and simple logging!") logger.debug("中文日志可以不") logger.error("严重错误")


8. 捕获异常
from loguru import logger @logger.catch def my_function(x, y, z): # An error? It's caught anyway! return 1 / (x + y + z)
9. 为日志添加颜色
import sys from loguru import logger logger.add(sys.stdout, colorize=True, format="<green>{time}</green> <level>{message}</level>")
10. 异步、线程安全、多进程安全
from loguru import logger logger.add("file.log", enqueue=True)
11. 全描述异常
记录代码中发生的异常对于跟踪错误很重要,但是如果您不知道为什么失败,则记录日志就毫无用处。 Loguru通过允许显示整个堆栈跟踪(包括变量值)来帮助您发现问题
from loguru import logger logger.add("output.log", backtrace=True, diagnose=True) # Set 'False' to not leak sensitive data in prod
12. 配置到flask
import logging import sys from pathlib import Path from flask import Flask from loguru import logger app = Flask(__name__) class InterceptHandler(logging.Handler): def emit(self, record): logger_opt = logger.opt(depth=6, exception=record.exc_info) logger_opt.log(record.levelname, record.getMessage()) def configure_logging(flask_app: Flask): """配置日志""" path = Path(flask_app.config['LOG_PATH']) if not path.exists(): path.mkdir(parents=True) log_name = Path(path, 'sips.log') logging.basicConfig(handlers=[InterceptHandler(level='INFO')], level='INFO') logger.configure(handlers=[{"sink": sys.stderr, "level": 'INFO'}]) # 配置日志到标准输出流 logger.add( log_name, rotation="500 MB", encoding='utf-8', colorize=False, level='INFO' ) # 配置日志到输出到文件
实例一个:
from loguru import logger logger.add("logger_3days.log", format="[{time:YYYY-MM-DD HH:mm:ss}] <lvl>{message}</lvl>", level="INFO", retention="3 days") logger.info("If you're using Python {}, prefer {feature} of course!", 3.6, feature="f-strings") logger.info("test info") logger.debug("test debug") logger.error("test error")
本文:Python: 日志记录方案 loguru, 日志模块, loguru模块, logger日志