python3 logging日志封装


一个完整的程序离不开日志,无论是开发阶段,还是测试阶段,亦或程序运行阶段,都可以通过日志查看程序的运行情况,或是定位问题。

下面是对 python3 的日志库 logging 进行了封装,对于大部分的需求应该是能满足的。

程序结构:

|--logger.py
|
|--singleton.py
|
|--runall.py
|
|--log
|  |
|  2022-2-16.log

logger.py

import os
import sys
import time
import logging
from .singleton import Singleton


@Singleton  # 如需打印不同路径的日志(运行日志、审计日志),则不能使用单例模式(注释或删除此行)。此外,还需设定参数name。
class Logger:
    def __init__(self, set_level="INFO",
                 name=os.path.split(os.path.splitext(sys.argv[0])[0])[-1],
                 log_name=time.strftime("%Y-%m-%d.log", time.localtime()),
                 log_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), "log"),
                 use_console=True):
        """
        :param set_level: 日志级别["NOTSET"|"DEBUG"|"INFO"|"WARNING"|"ERROR"|"CRITICAL"],默认为INFO
        :param name: 日志中打印的name,默认为运行程序的name
        :param log_name: 日志文件的名字,默认为当前时间(年-月-日.log)
        :param log_path: 日志文件夹的路径,默认为logger.py同级目录中的log文件夹
        :param use_console: 是否在控制台打印,默认为True
        """
        if not set_level:
            set_level = self._exec_type()  # 设置set_level为None,自动获取当前运行模式
        self.__logger = logging.getLogger(name)
        self.setLevel(
            getattr(logging, set_level.upper()) if hasattr(logging, set_level.upper()) else logging.INFO)  # 设置日志级别
        if not os.path.exists(log_path):  # 创建日志目录
            os.makedirs(log_path)
        formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s - %(message)s")
        handler_list = list()
        handler_list.append(logging.FileHandler(os.path.join(log_path, log_name), encoding="utf-8"))
        if use_console:
            handler_list.append(logging.StreamHandler())
        for handler in handler_list:
            handler.setFormatter(formatter)
            self.addHandler(handler)

    def __getattr__(self, item):
        return getattr(self.logger, item)

    @property
    def logger(self):
        return self.__logger

    @logger.setter
    def logger(self, func):
        self.__logger = func

    def _exec_type(self):
        return "DEBUG" if os.environ.get("IPYTHONENABLE") else "INFO"

singleton.py

class Singleton:
    """
    单例装饰器。
    """
    __cls = dict()

    def __init__(self, cls):
        self.__key = cls

    def __call__(self, *args, **kwargs):
        if self.__key not in self.cls:
            self[self.__key] = self.__key(*args, **kwargs)
        return self[self.__key]

    def __setitem__(self, key, value):
        self.cls[key] = value

    def __getitem__(self, item):
        return self.cls[item]

    @property
    def cls(self):
        return self.__cls

    @cls.setter
    def cls(self, cls):
        self.__cls = cls

runall.py

#coding=utf-8

from .logger import Logger

log = Logger("debug")

log .critical("这是一个 critical 级别的问题!")
log .error("这是一个 error 级别的问题!")
log .warning("这是一个 warning 级别的问题!")
log .info("这是一个 info 级别的问题!")
log .debug("这是一个 debug 级别的问题!")

来源:https://www.jb51.net/article/184274.htm