当前位置:网站首页>封装logging模块
封装logging模块
2022-04-23 14:02:00 【沉觞流年】
封装logging模块
上篇文章,简要介绍了 Python中的logging日志模块
简单封装
logging日志功能,可以将其封装成一个独立的模块,这样,在需要使用到日志功能的地方,导入这个模块即可以使用
my_logger.py
import logging
class LoggerHandler():
# 初始化 Logger
def __init__(self,
name='root',
logger_level= 'DEBUG',
file=None,
logger_format = '%(asctime)s-%(message)s'
# logger_format = '%(asctime)s-%(filename)s-%(lineno)d-%(message)s'
):
# 1、初始化logger收集器
logger = logging.getLogger(name)
# 2、设置日志收集器level级别
logger.setLevel(logger_level)
# 5、初始化 handler 格式
fmt = logging.Formatter(logger_format)
# 3、初始化日志处理器
# 如果传递了文件,就会输出到file文件中
if file:
file_handler = logging.FileHandler(file)
# 4、设置 file_handler 级别
file_handler.setLevel(logger_level)
# 6、设置handler格式
file_handler.setFormatter(fmt)
# 7、添加handler
logger.addHandler(file_handler)
# 默认都输出到控制台
stream_handler = logging.StreamHandler()
# 4、设置 stream_handler 级别
stream_handler.setLevel(logger_level)
# 6、设置handler格式
stream_handler.setFormatter(fmt)
# 7、添加handler
logger.addHandler(stream_handler)
# 设置成实例属性
self.logger = logger
# 返回日志信息
def debug(self,msg):
return self.logger.debug(msg)
def info(self,msg):
return self.logger.info(msg)
def warning(self,msg):
return self.logger.warning(msg)
def error(self,msg):
return self.logger.error(msg)
def critical(self,msg):
return self.logger.critical(msg)
这样,需要用到日志的时候,通过导入 my_logger
模块,使用 LoggerHandler
类里的 debug
和info
函数即可
这种封装方式,相当于重写了一个日志模块的功能
然而,如果将init
里的内容,换成logger_format = '%(asctime)s-%(filename)s-%(lineno)d-%(message)s'
这种封装,会出现一些小问题,行号和文件会显示错误
新建立一个 test.py
文件
test.py
import my_logger
if __name__ == '__main__':
logger = my_logger.LoggerHandler()
logger.info('hello world!')
执行这个文件,打印的内容为:2021-08-29 21:12:25,462-my_logger.py-53-hello world!
,这里的行号为 53
,日志里的文件名称为my_logger.py
也就是说,打印的文件和行号,是封装的内容里的,而不是我们执行的 test.py
文件里的内容
这个问题出在了 1、初始化logger收集器 logger = logging.getLogger(name)
这一步
test.py
文件里调用的是LoggerHandler
类的内容,logger
初始化的时候,就已经把日志信息保存起来了,所以,调用 info
函数的时候, return self.logger.info(msg)
返回的是LoggerHandler
类的info
函数 logger
的内容
继承 logging 模块进行封装
如果要解决这个问题,就不要像上面一样,重写日志模块的功能,而是要采用继承 logging 模块的方式,去封装日志模块
logging 模块
中有一个 Logger 类
,所以,在定义类的时候,需要继承这个 Logger 类
按住Ctrl,点击 logger = logging.getLogger(name)
中的 getLogger
,查看getLogger
方法的内容
def getLogger(name=None):
""" Return a logger with the specified name, creating it if necessary. If no name is specified, return the root logger. """
if name:
return Logger.manager.getLogger(name)
else:
return root
备注的内容为:返回具有指定名称的日志收集器,并在必要时创建它。如果没有指定名称,则返回根日志收集器。
从备注中可以得知,这个函数的作用,是返回logger收集器。
按住Ctrl,点击 manager.getLogger(name)
中的 getLogger
,
里面有这样一行代码: rv = (self.loggerClass or _loggerClass)(name)
,
这行代码的作用,其实就是实例化一个类(日志Logger的类)。
所以,上面的问题,1、初始化logger收集器 logger = logging.getLogger(name)
这一步,实例化的是LoggerHandler
类,在 test.py
文件里打印的日志内容,返回的是LoggerHandler
类的info
函数 logger
的行号和文件名称
而采用继承的方式,继承logging 模块
中 Logger 类
,就不会出现这个问题了,因为调用的是logging 模块
中 Logger 类
,打印的日志内容,调用的的是logging 模块
的info
函数了,返回的行号和文件名称,就是正确的
所以,就不需要1、初始化logger收集器 logger = logging.getLogger(name)
这一步了,直接super().__init__(name)
继承logging 模块
中 Logger 类
,将相应的内容,替换成 self
就行了,也不需要再自定义 debug
、info
这些方法了
my_logger2.py
import logging
class LoggerHandler(logging.Logger):
# 初始化 Logger
def __init__(self,
name='root',
logger_level= 'DEBUG',
file=None,
logger_format = " [%(asctime)s] %(levelname)s %(filename)s [ line:%(lineno)d ] %(message)s"
):
# 1、设置logger收集器,继承logging.Logger
super().__init__(name)
# 2、设置日志收集器level级别
self.setLevel(logger_level)
# 5、设置 handler 格式
fmt = logging.Formatter(logger_format)
# 3、设置日志处理器
# 如果传递了文件,就会输出到file文件中
if file:
file_handler = logging.FileHandler(file)
# 4、设置 file_handler 级别
file_handler.setLevel(logger_level)
# 6、设置handler格式
file_handler.setFormatter(fmt)
# 7、添加handler
self.addHandler(file_handler)
# 默认都输出到控制台
stream_handler = logging.StreamHandler()
# 4、设置 stream_handler 级别
stream_handler.setLevel(logger_level)
# 6、设置handler格式
stream_handler.setFormatter(fmt)
# 7、添加handler
self.addHandler(stream_handler)
test.py
import my_logger2
if __name__ == '__main__':
logger = my_logger2.LoggerHandler()
logger.info('hello world!')
执行 test.py
文件 ,可以发现,打印的日志信息为:
[2021-08-29 22:47:33,124] INFO mytest.py [ line:5 ] hello world!
,这个就正确了
如果还想在日志中看到对应模块中的函数名称,可以再加上 funcName
即:logger_format = " [%(asctime)s] %(levelname)s [%(filename)s %(funcName)s] [ line:%(lineno)d ] %(message)s"
版权声明
本文为[沉觞流年]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_44614026/article/details/119985629
边栏推荐
- JS force deduction brush question 103 Zigzag sequence traversal of binary tree
- 理解虚基类、虚函数与纯虚函数的概念(转)
- centOS下mysql主从配置
- 关于stream流,浅记一下------
- Chapter 15 new technologies of software engineering
- Kettle -- control parsing
- STM32学习记录0007——新建工程(基于寄存器版)
- Basic knowledge learning record
- jacob打印word
- Android interview theme collection
猜你喜欢
随机推荐
Interesting talk about network protocol
Lin Lin, product manager of Lenovo: network failure of local network operator in Tianjin. The background server of Zui system can't work normally for the time being
Record a strange bug: component copy after cache component jump
1256:献给阿尔吉侬的花束
分页SQL
项目中遇到的问题(五)操作Excel接口Poi的理解
JMeter pressure test tool
mysql新表,自增id长达20位,原因竟是......
淘宝发布宝贝提示“您的消保保证金额度不足,已启动到期保障”
Nacos+AspnetCore+Ocelot实战编码
Un modèle universel pour la construction d'un modèle d'apprentissage scikit
基於CM管理的CDH集群集成Phoenix
第十五章 软件工程新技术
Quartus Prime硬件实验开发(DE2-115板)实验一CPU指令运算器设计
Oracle alarm log alert Chinese trace and trace files
Pytorch 经典卷积神经网络 LeNet
linux MySQL数据定时dump
Go语言 RPC通讯
9月8日,临去松山湖的前夜
SPC简介