python 二次封装logging,导致日志输出的filename错误及优化封装

问题

封装logging文件名称为:A.py

调用A模块的文件名称为:B.py

二次封装了logging日志模块,根据需要,传入level,判断等级,调用logging模块的info、debug等日志输出的方法;使用过程中发现,在B文件调用logging模块的方法,打印的filename为A.py,就是还是在日志封装文件,而非是调用的文件,导致出错,也只能看到是日志封装文件,而不知道具体是哪个文件报错了;

 输出的日志文件,filename不是xx_mysql.py,而是my_log.py

原始代码_打印的filename不对

原始的my_log.py文件的代码_打印的filename不对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class MyLog:
    def my_log(self, level, msg):
        my_logger = logging.getLogger("logsMessage")
 
        my_logger.setLevel("DEBUG")   # 设置日志的收集级别
 
        # 设置日志的输出格式
        formatter = logging.Formatter('%(asctime)s-%(levelname)s-%(filename)s-%(name)s-日志信息:%(message)s')
 
        # ---- === 日志可输出到日志和具体的文件 ===
        ch = logging.StreamHandler()
        ch.setFormatter(formatter)
 
        # 2、 输出到制定文件,将日志信息收集到文件
        # 3、 输出到文件拓展,每天生成一个文件,保存近5天的的log文件,防止文件过大的
        logs_path = os.path.join(project_path.logs_path_day, 'log')
 
        # 先将when改成Minutes,每隔2分钟,生成一个文件  interval=1,
        file_hander = TimedRotatingFileHandler(filename=logs_path, when='midnight')
 
        # 设置生成日志文件名的格式,以年-月-日来命名
        # suffix设置,会生成文件名为log.2020-02-25.log # 按时间S的 命名格式 %Y-%m-%d %H-%M-%S.log
        file_hander.suffix = "%Y-%m-%d.log"
 
        # extMatch是编译好正则表达式,用于匹配日志文件名后缀
        # 需要注意的是suffix和extMatch一定要匹配的上,如果不匹配,过期日志不会被删除。
        file_hander.extMatch = re.compile(r"^\d{4}-\d{2}-\d{2}.log$")
        file_hander.setFormatter(formatter)
 
        # 日志收集器添加一个渠道,分别将输出到控制台、输出到具体文件的日志收集器,添加到渠道
        my_logger.addHandler(ch)
        my_logger.addHandler(file_hander)
 
        # 传进日志级别,根据级别,输出对应的级别的日志信息
        if level == 'DEBUG':
            my_logger.debug(msg)
        elif level == 'INFO':
            my_logger.info(msg)
        elif level == 'WARNING':
            my_logger.warning(msg)
        elif level == 'ERROR':
            my_logger.error(msg)
        elif level == 'EXCEPTION':
            my_logger.exception(msg)
        elif level == 'CRITICAL':
            my_logger.critical(msg)
 
        my_logger.removeHandler(ch)
        my_logger.removeHandler(file_hander)
 
    def debug(self, msg):
        """
        输出日志级别为debug的日志
        msg:日志信息
        """
        self.my_log("DEBGU", msg)

原因是,请参考logging的源码

https://blog.csdn.net/qq_34026204/article/details/125810425

解决方法_使用logger使用

不再进行info、debug等方法的二次封装,直接通过logger.info(),输出日志,打印的文件名正确

遇到问题:结合pytest使用时,pytest有带log,导致pytest执行用例时,不输出日志,日志也没有写入到文件;

文件Log_print.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class LogPrint:
    def __init__(self):
        # my_logger,获取到getLogger().info(),获取到的filename正确,但通过封装后,filename则是当前logname
        self.logger = logging.getLogger()
 
        # 设置日志的收集级别, 必须要设置为DEBUG,默认收集warning级别以上的错误(不设置收集不到info error的日志)
        self.logger.setLevel("DEBUG")
 
        # 当前已有handler,则不再新增,使用已有的handlers打印和输出日志     !!! 结合pytest使用时,pytest有带log,导致pytest执行用例时,不输出日志,日志也没有写入到文件
        if not self.logger.handlers:
            formatter = logging.Formatter('%(asctime)s-%(levelname)s-[%(filename)s:%(lineno)s]-日志信息:%(message)s')
 
            # === 1、设置控制台的输出渠道 设置日志输出的格式===
            ch = logging.StreamHandler()
            ch.setFormatter(formatter)
 
            # === 2、设置定期生成的日志文件的渠道 ====
            logs_path = os.path.join(GetPath.logs_path_day, 'log')
            file_hander = TimedRotatingFileHandler(filename=logs_path, when='midnight', backupCount=7)
 
            # suffix和extMatch要与设置的when匹配,若设置为日,则传入的正则suffix应该是日:"%Y-%m-%d.log"
            file_hander.suffix = "%Y-%m-%d.log"
 
            # suffix和extMatch一定要匹配的上,如果不匹配,过期日志不会被删除。 re.compile(r"^\d{4}-\d{2}-\d{2}.log$")
            file_hander.extMatch = r"^\d{4}-\d{2}-\d{2}.log$"
            file_hander.extMatch = re.compile(file_hander.extMatch)
            file_hander.setFormatter(formatter)
 
            # 将设置好的渠道,添加到日志收集器
            self.logger.addHandler(ch)
            self.logger.addHandler(file_hander)

再次优化的log:

优化,初始化log时,将现有的都移除掉,重新创建!!!

 

复制代码
class LogPrint:

    def __init__(self):
        self.logger = logging.getLogger()
        self.logger.setLevel("DEBUG")

        # == 1、将现有的handlers移除,后面再创建 ==
        while self.logger.hasHandlers():
            for handler in self.logger.handlers:
                self.logger.removeHandler(handler)

        self.log_colors_config = {
            'DEBUG': 'cyan',
            'INFO': 'green',
            'WARNING': 'yellow',
            'ERROR': 'red',
            'CRITICAL': 'red',
        }

        self.color_fmt = colorlog.ColoredFormatter(
            '%(log_color)s%(asctime)s [%(filename)s:%(funcName)s:%(lineno)s] [%(levelname)s]: %(message)s',
            log_colors=self.log_colors_config)

        # -日志信息
        self.formatter = logging.Formatter(
            '%(asctime)s [%(filename)s:%(funcName)s:%(lineno)s] [%(levelname)s]: %(message)s')

        self.logger.addHandler(self.get_console_handler())
        self.logger.addHandler(self.get_file_handler())
复制代码

具体使用

1
2
from Common.log_print import LogPrint
LogPrint().logger.info("log print test")

 输出日志

参考:https://blog.csdn.net/Moonlight_16/article/details/123334339

posted on   刚刚好1  阅读(1565)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示