一、 代码如下
# -*-coding:utf8-*-
import logging
class MyLogging(object):
def __new__(cls, level='DEBUG', **channels):
"""
:param level: 日志输出等级--->str
:param channels: ---> 日志输出渠道--->dict,如: {'file':'my_log.log','console':''}
:return:
"""
# 1. 创建自己的日志收集器
my_log = logging.getLogger("my_log")
# 2. 设置收集的日志等级,设置为INFO,即,输出等级为INFO以及等级高于INFO等级的日志
levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
level_u = level.upper()
if level_u in levels:
my_log.setLevel(level_u)
# 3. 设置输出渠道
expect_channels = ['console', 'file']
for channel in channels:
chanel_l = channel.lower()
if chanel_l in expect_channels:
if chanel_l == 'console':
c_l = logging.StreamHandler()
c_l.setLevel(level_u) # 设定输出到控制台的log等级
my_log.addHandler(c_l)
else:
f_l = logging.FileHandler(filename=channels[channel], encoding="utf8")
f_l.setLevel(level_u) # 设定输出到控制台的log信息等级
my_log.addHandler(f_l)
# 4. 日志格式设置
# 工作中常用格式,可以实现:输出日志的打印时间,那个模块的哪一个行输出的,输出的体制规则时什么,以及输入的日志内容
formatter = '%(asctime)s--->[%(filename)s--->%(funcName)s-->line:%(lineno)d] - %(levelname)s: %(message)s'
ft = logging.Formatter(formatter)
c_l.setFormatter(ft)
f_l.setFormatter(ft)
return my_log
my_log = MyLogging('DEBUG', **{'file': 'my_log1.log', 'console': ''})
my_log2 = MyLogging('DEBUG', **{'file': 'my_log2.log', 'console': ''})
# 5. 日志输出
my_log.error("error")
my_log.critical("critical")
二、 问题截图显示

三、 原因:
打断点,查看调试窗口数据内容如下:




**在进行日志打印时,也就是在调用info,debug等方法时,先回进入这么一个流程:根据getLogger(name)里的name获取Logger,而我们代码中创建的logging.getLogger(name)中name都等于my_log,所以在第一次MyLogging实例化时,就已经添加了StreamHandle,第二次实例时,name还是my_log,那么handler这个logger就又有了一个同样的handler,所以就会打印多次**
四、解决方案
方案1: 只创建一个日志对象 ---- 人工控制

方案2: log实例时,name不一样
(修改__new__方法,参数增加name) ----- 人为控制


方案3: __new__方法中做处理,只允许创建一个Logger对象

结果运行:
版权声明:本文为weixin_41256550原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。