python--log

Ref: Loguru:Python 日志终极解决方案

loguru功能介绍#

add(
    sink,
    *,
    level='DEBUG',
    format='<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | '
           '<level>{level: <8}</level> | '
           '<cyan>{name}</cyan>:'
           '<cyan>{function}</cyan>:'
           '<cyan>{line}</cyan> - '
           '<level>{message}</level>',
    filter=None,
    colorize=None,
    serialize=False,
    backtrace=True,
    diagnose=True,
    enqueue=False,
    catch=True,
    **kwargs
)

基本参数释义:

  • sink:可以是一个 file 对象,例如 sys.stderropen('file.log', 'w'),也可以是 str 字符串或者 pathlib.Path 对象,即文件路径,也可以是一个方法,可以自行定义输出实现,也可以是一个 logging 模块的 Handler,比如 FileHandler、StreamHandler 等,还可以是 coroutine function,即一个返回协程对象的函数等。
  • level:日志输出和保存级别。
  • format:日志格式模板。
  • filter:一个可选的指令,用于决定每个记录的消息是否应该发送到 sink。
  • colorize:格式化消息中包含的颜色标记是否应转换为用于终端着色的 ansi 代码,或以其他方式剥离。 如果没有,则根据 sink 是否为 tty(电传打字机缩写) 自动做出选择。
  • serialize:在发送到 sink 之前,是否应首先将记录的消息转换为 JSON 字符串。
  • backtrace:格式化的异常跟踪是否应该向上扩展,超出捕获点,以显示生成错误的完整堆栈跟踪。
  • diagnose:异常跟踪是否应显示变量值以简化调试。建议在生产环境中设置 False,避免泄露敏感数据。
  • enqueue:要记录的消息是否应在到达 sink 之前首先通过多进程安全队列,这在通过多个进程记录到文件时很有用,这样做的好处还在于使日志记录调用是非阻塞的。
  • catch:是否应自动捕获 sink 处理日志消息时发生的错误,如果为 True,则会在 sys.stderr 上显示异常消息,但该异常不会传播到 sink,从而防止应用程序崩溃。
  • __kwargs:仅对配置协程或文件接收器有效的附加参数(见下文)。

当且仅当 sink 是协程函数时,以下参数适用:

  • loop:将在其中调度和执行异步日志记录任务的事件循环。如果为 None,将使用 asyncio.get_event_loop() 返回的循环。

当且仅当 sink 是文件路径时,以下参数适用:

  • rotation:一种条件,指示何时应关闭当前记录的文件并开始新的文件。
  • *retention *:过滤旧文件的指令,在循环或程序结束期间会删除旧文件。
  • compression:日志文件在关闭时应转换为的压缩或存档格式。
  • delay:是在配置 sink 后立即创建文件,还是延迟到第一条记录的消息时再创建。默认为 False
  • mode:内置 open() 函数的打开模式,默认为 a(以追加模式打开文件)。
  • buffering:内置 open() 函数的缓冲策略,默认为1(行缓冲文件)。
  • encoding:内置 open() 函数的文件编码
  • __kwargs:其他传递给内置 open() 函数的参数。

这么多参数可以见识到 add() 函数的强大之处,仅仅一个函数就能实现 logging 模块的诸多功能,接下来介绍几个比较常用的方法。

rotation 日志文件分隔#

add() 函数的 rotation 参数,可以实现按照固定时间创建新的日志文件,比如设置每天 0 点新创建一个 log 文件:

logger.add('runtime_{time}.log', rotation='00:00')

设置超过 500 MB 新创建一个 log 文件:

logger.add('runtime_{time}.log', rotation="500 MB")

设置每隔一个周新创建一个 log 文件:

logger.add('runtime_{time}.log', rotation='1 week')

retention 日志保留时间#

add() 函数的 retention 参数,可以设置日志的最长保留时间,比如设置日志文件最长保留 15 天:

logger.add('runtime_{time}.log', retention='15 days')

设置日志文件最多保留 10 个:

logger.add('runtime_{time}.log', retention=10)

也可以是一个 datetime.timedelta 对象,比如设置日志文件最多保留 5 个小时:

import datetime from loguru import logger logger.add('runtime_{time}.log', retention=datetime.timedelta(hours=5))

compression 日志压缩格式#

add() 函数的 compression 参数,可以配置日志文件的压缩格式,这样可以更加节省存储空间,比如设置使用 zip 文件格式保存:

logger.add('runtime_{time}.log', compression='zip')

其格式支持:gzbz2xzlzmatartar.gztar.bz2tar.xz

字符串格式化#

Loguru 在输出 log 的时候还提供了非常友好的字符串格式化功能,相当于 str.format()

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

loguru 封装类#

"""
loguru 封装类,导入即可直接使用
# 当前文件名 logger.py
"""

from functools import wraps
import sys
import datetime
import loguru
from pathlib import Path
import os
import configparser


# 单例类的装饰器
def singleton_class_decorator(cls):
    """
    装饰器,单例类的装饰器
    """
    # 在装饰器里定义一个字典,用来存放类的实例。
    _instance = {}

    # 装饰器,被装饰的类
    @wraps(cls)
    def wrapper_class(*args, **kwargs):
        # 判断,类实例不在类实例的字典里,就重新创建类实例
        if cls not in _instance:
            # 将新创建的类实例,存入到实例字典中
            _instance[cls] = cls(*args, **kwargs)
        # 如果实例字典中,存在类实例,直接取出返回类实例
        return _instance[cls]

    # 返回,装饰器中,被装饰的类函数
    return wrapper_class


@singleton_class_decorator
class Logger:
    def __init__(self):
        self.logger_add()

    def get_project_path(self, project_path=None):
        if project_path is None:
            # 当前项目文件的,绝对真实路径
            # 路径,一个点代表当前目录,两个点代表当前目录的上级目录
            project_path = Path(__file__).parent.parent
        # 返回当前项目路径
        return project_path

    def get_log_path(self):
        # 项目目录
        project_path = self.get_project_path()
        # 项目日志目录
        project_log_dir = Path(project_path, 'Logs')
        # 日志文件名
        project_log_filename = 'tmzx_{}.log'.format(datetime.date.today())
        # 日志文件路径
        project_log_path = Path(project_log_dir, project_log_filename)

        return project_log_path

    def logger_add(self):
        # 清空所有设置
        loguru.logger.remove()

        loguru.logger.add(
            # 控制台打印
            sys.stderr,
            format="[<green>{time:YYYY-MM-DD HH:mm:ss}</green>  "  # 颜色>时间
                   "<level>{level:<8}|{module}:{line}]</level>"  # 模块名.方法名
                   "<level>{message}</level>",  # 日志内容
            level="INFO",
        )

        # 文件保存
        project_log_path = self.get_log_path()
        loguru.logger.add(
            # 保存的路径
            sink=project_log_path,
            # 日志创建周期
            rotation="10MB",
            # 保存
            retention="30 days",
            # 文件的压缩格式
            compression='zip',
            # 编码格式
            encoding="utf-8",
            # 支持异步存储
            enqueue=True,
            # 输出格式
            format="[{time:YYYY-MM-DD HH:mm:ss} {level:<8} | {file}:{line}] {message}",
            level="INFO",
        )

    @property
    def get_logger(self):
        return loguru.logger


'''
# 实例化日志类
'''
logger = Logger().get_logger

posted @   深夜好梦  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示
主题色彩