python将logging模块封装成单独模块并实现动态切换Level方式


Posted in Python onMay 12, 2020

查找了很多资料,但网上给出的教程都是大同小异的,而我想将代码进一步精简,解耦,想实现如下两个目标

1. 将logging模块的初始化,配置,设置等代码封装到一个模块中;

2. 能根据配置切换logging.level, 网上给出的教程都是写死的,如果我在线上之前使用了logging.info(msg),现在想切换为logging.debug(msg)怎么办?需要能够根据配置文件中的 设置配置logging.level

两个文件:

logging_class:将logging模块的初始化,配置,设置等代码封装到一此模块中,读取配置文件中对于log等级的设置项;需要使用log功能的模块import 这个模块

applogconfig.ini: 配置文件

logging_class:

import logging
import sys
import ConfigParser
 
def log_building(log_file):
 try:
 #set format 
 format_str=logging.Formatter("%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s")
 
 #create stander output handler
 crit_hand=logging.StreamHandler(sys.stderr)
 crit_hand.setFormatter(format_str)
 
 #create file handler
 file_hand=logging.FileHandler(log_file,'a')
 file_hand.setFormatter(format_str)
 
 app_log=logging.getLogger(__name__)
 app_log.addHandler(crit_hand)
 app_log.addHandler(file_hand)
 
 #必须设置,否则无法输出
 app_log.setLevel(logging.NOTSET)
 
 return app_log
 except Exception as e:
 logging.shutdown()
 raise e
 
def config_file_get(fpath):
 try:
 cnf_dict={}
 cfg=ConfigParser.SafeConfigParser()
 cfg.read(fpath)
 for section in cfg.sections():
  #将ini中的item组合到字典中,key=section+_option
  for item in cfg.items(section):
  key= section+'_'+item[0]
  value=item[1]
  if cnf_dict.get(key,None)==None:
   cnf_dict[key]=value
   
  
 return cnf_dict
 except Exception as e:
 raise e
def log_level_get(level):
 DEBUG_LEVEL={'CRITICAL':logging.CRITICAL,'ERROR':logging.ERROR,'WARNING':logging.WARNING,
   'INFO':logging.INFO,'DEBUG':logging.DEBUG
 }
 
 try:
 return DEBUG_LEVEL.get(level.upper())
 except Exception as e:
 raise e

applogconfig.ini内容:

[log]
log_level=ERROR
dir=log

以下为unittest内容:

import unittest
import logging_class
import os
import logging
 
class Test(unittest.TestCase):
 
 
 cfg={}
 def setUp(self):
 print 'test begin'
 self.cfg={}
 
 
 def tearDown(self):
 print 'test end'
 
 def testlog_level_get(self):
 currentWorkingPath = r'E:\Myworkspace\python\logging_module\logging_module'
 
 ini_file=os.path.normpath(os.path.abspath(os.path.join(currentWorkingPath,'applogconfig.ini')))
 self.cfg=logging_class.config_file_get(ini_file)
 self.assertEqual(self.cfg['log_log_level'].upper(), 'ERROR', 'OK')
 
 def testlog_level_set(self):
 currentWorkingPath = r'E:\Myworkspace\python\logging_module\logging_module'
 ini_file=os.path.normpath(os.path.abspath(os.path.join(currentWorkingPath,'applogconfig.ini')))
 self.cfg=logging_class.config_file_get(ini_file)
 
 #print self.cfg['log_log_level']
 self.assertEqual(logging_class.log_level_get(self.cfg['log_log_level']), logging.ERROR, 'OK')
 def testlog_building(self):
 currentWorkingPath = r'E:\Myworkspace\python\logging_module\logging_module'
 ini_file=os.path.normpath(os.path.abspath(os.path.join(currentWorkingPath,'applogconfig.ini')))
 log_file=os.path.normpath(os.path.abspath(os.path.join(currentWorkingPath,'b.log')))
 self.cfg=logging_class.config_file_get(ini_file)
 
 #print self.cfg['log_log_level']
 level=logging_class.log_level_get(self.cfg['log_log_level'])
 log=logging_class.log_building(log_file)
 log.log(level, 'dddds')
 
 log.debug('msg')
 
if __name__ == "__main__":
 #import sys;sys.argv = ['', 'Test.testName']
 unittest.main()

输出:

Finding files... done.
Importing test modules ... done.

test begin
test end
test begin
test end
test begin
2016-12-15 17:59:04,059 logging_module_test.py[line:48] ERROR dddds
test end
----------------------------------------------------------------------
Ran 3 tests in 0.004s

补充知识:一种logging封装方法,不会产生重复log

在调试logging的封装的时候,发现已经调用了logging封装的函数,在被其它函数再调用时,会出现重复的logging。原因是不同的地方创建了不同的handler,所以会重复,可以使用暴力方法解决

暴力方式就是每次创建新的对象就清空logger.handlers

我常用的封装如下

import logging
import time,os
'''
 使用方法:
 import mylog
 log = mylog.Log().getlog()
 log.debug("###")
'''
class Log():

 def __init__(self,logger="mylog"):
 self.logger = logging.getLogger(logger)
 self.logger.setLevel(logging.DEBUG)
 self.log_time = "\\"+time.strftime("%Y-%m-%d_%H_%M", time.localtime())+".log"
 # 在进程路径创建log文件夹
 # self.log_path = os.path.join(os.getcwd() + "\\log")
 # 固定在mylog上一级创建
 self.log_path = os.path.join(os.path.dirname(os.path.dirname(__file__)) + "\\log")
 if os.path.exists(self.log_path) and os.path.isdir(self.log_path):
  pass
 else:
  os.makedirs(self.log_path)
 self.log_name = os.path.join(self.log_path + self.log_time)

 #因为多出调用logger会生成多个handlers,所以每次调用清空handler
 self.logger.handlers = [] 
 fh = logging.FileHandler(self.log_name, 'a', encoding='utf-8')
 formatter = logging.Formatter('[%(levelname)s][%(asctime)s] [%(filename)s]->[%(funcName)s] line:%(lineno)d ---> %(message)s')
 fh.setLevel(logging.DEBUG)
 fh.setFormatter(formatter)
 self.logger.addHandler(fh)
 
 ch = logging.StreamHandler()
 ch.setLevel(logging.DEBUG)
 ch.setFormatter(formatter)
 self.logger.addHandler(ch)
 
 fh.close()


 def getlog(self):
 return self.logger

if __name__ == "__main__":
 log = Log().getlog()
 log.debug("hello")

以上这篇python将logging模块封装成单独模块并实现动态切换Level方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
Jun 10 Python
Python3.0与2.X版本的区别实例分析
Aug 25 Python
Python文件右键找不到IDLE打开项解决办法
Jun 08 Python
基于Python对数据shape的常见操作详解
Dec 25 Python
使用python opencv对目录下图片进行去重的方法
Jan 12 Python
Django框架搭建的简易图书信息网站案例
May 25 Python
python 循环数据赋值实例
Dec 02 Python
python爬取王者荣耀全皮肤的简单实现代码
Jan 31 Python
python 非线性规划方式(scipy.optimize.minimize)
Feb 11 Python
Django自定义列表 models字段显示方式
Apr 03 Python
python argparse传入布尔参数false不生效的解决
Apr 20 Python
python实现猜拳游戏项目
Nov 30 Python
Python PyQt5模块实现窗口GUI界面代码实例
May 12 #Python
从0到1使用python开发一个半自动答题小程序的实现
May 12 #Python
Python列表去重复项的N种方法(实例代码)
May 12 #Python
python3中的logging记录日志实现过程及封装成类的操作
May 12 #Python
Pycharm激活方法及详细教程(详细且实用)
May 12 #Python
PyTorch在Windows环境搭建的方法步骤
May 12 #Python
pycharm 2018 激活码及破解补丁激活方式
Sep 21 #Python
You might like
使用PHP实现密保卡功能实现代码<打包下载直接运行>
2011/10/09 PHP
php下载文件,添加响应头的简单实例
2016/09/22 PHP
thinkPHP5.0框架引入Traits功能实例分析
2017/03/18 PHP
JavaScript中的面向对象介绍
2012/06/30 Javascript
jQuery select表单提交省市区城市三级联动核心代码
2014/06/09 Javascript
prototype框架中美元符号$用法分析
2016/01/22 Javascript
Bootstrap的class样式小结
2016/12/01 Javascript
angularjs中ng-attr的用法详解
2016/12/31 Javascript
原生js实现弹出层效果
2017/01/20 Javascript
Angularjs 根据一个select的值去设置另一个select的值方法
2018/08/13 Javascript
基于vue的验证码组件的示例代码
2019/01/22 Javascript
小程序开发踩坑:页面窗口定位(相对于浏览器定位)(推荐)
2019/04/25 Javascript
浅谈webpack 四个核心概念之Entry
2019/06/12 Javascript
nodejs实现UDP组播示例方法
2019/11/04 NodeJs
vue 重塑数组之修改数组指定index的值操作
2020/08/09 Javascript
解决基于 keep-alive 的后台多级路由缓存问题
2020/12/23 Javascript
[00:31]2016完美“圣”典风云人物:国士无双宣传片
2016/12/04 DOTA
[02:58]魔廷新尊——痛苦女王至宝语音台词节选
2020/06/14 DOTA
快速查询Python文档方法分享
2017/12/27 Python
Python实现TCP探测目标服务路由轨迹的原理与方法详解
2019/09/04 Python
python向图片里添加文字
2019/11/26 Python
解决c++调用python中文乱码问题
2020/07/29 Python
详解Pycharm第三方库的安装及使用方法
2020/12/29 Python
美国二手复古奢侈品包包购物网站:LXRandCo
2019/06/18 全球购物
最新的咖啡店创业计划书
2013/12/30 职场文书
产品推广策划方案
2014/05/10 职场文书
小学生美德少年事迹材料
2014/08/24 职场文书
银行员工犯错检讨书
2014/09/16 职场文书
政风行风自查自纠报告
2014/10/21 职场文书
2014年教师工作总结
2014/11/10 职场文书
英文版辞职信
2015/02/28 职场文书
2015年学校党支部工作总结
2015/04/01 职场文书
二审代理词范文
2015/05/25 职场文书
Python爬虫中urllib3与urllib的区别是什么
2021/07/21 Python
Python实现简单的俄罗斯方块游戏
2021/09/25 Python
springboot创建的web项目整合Quartz框架的项目实践
2022/06/21 Java/Android