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爬虫辅助利器PyQuery模块的安装使用攻略
Apr 24 Python
50行Python代码实现人脸检测功能
Jan 23 Python
完美解决在oj中Python的循环输入问题
Jun 25 Python
Python给定一个句子倒序输出单词以及字母的方法
Dec 20 Python
python lxml中etree的简单应用
May 10 Python
使用python制作一个为hex文件增加版本号的脚本实例
Jun 12 Python
Python 写入训练日志文件并控制台输出解析
Aug 13 Python
Python autoescape标签用法解析
Jan 17 Python
在Tensorflow中实现梯度下降法更新参数值
Jan 23 Python
vue常用指令代码实例总结
Mar 16 Python
pandas apply使用多列计算生成新的列实现示例
Feb 24 Python
用Python提取PDF表格的方法
Apr 11 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
phpmailer中文乱码问题的解决方法
2014/04/22 PHP
php生成图片缩略图的方法
2015/04/07 PHP
php中PDO方式实现数据库的增删改查
2015/05/17 PHP
PHP中的常见魔术方法功能作用及用法实例
2015/07/01 PHP
6个常见的 PHP 安全性攻击实例和阻止方法
2020/12/16 PHP
JavaScript 数组的 uniq 方法
2008/01/23 Javascript
css3元素简单的闪烁效果实现(html5 jquery)
2013/12/28 Javascript
jQuery中:animated选择器用法实例
2014/12/29 Javascript
微信JS接口汇总及使用详解
2015/01/09 Javascript
jQuery实现点击图片翻页展示效果的方法
2015/02/16 Javascript
总结JavaScript三种数据存储方式之间的区别
2016/05/03 Javascript
深入理解jquery中的事件与动画
2016/05/24 Javascript
Bootstrap3.0建站教程(一)之bootstrap表单元素排版
2016/06/01 Javascript
iscroll实现下拉刷新功能
2017/07/18 Javascript
新手vue构建单页面应用实例代码
2017/09/18 Javascript
vuex中的 mapState,mapGetters,mapActions,mapMutations 的使用
2018/04/13 Javascript
详解使用create-react-app添加css modules、sasss和antd
2018/07/31 Javascript
js代码实现轮播图
2020/05/04 Javascript
[03:10]超级美酒第四天 fy拉比克秀 大合集
2018/06/05 DOTA
python笔记(1) 关于我们应不应该继续学习python
2012/10/24 Python
python dataframe 输出结果整行显示的方法
2018/06/14 Python
对python数据切割归并算法的实例讲解
2018/12/12 Python
详解Python绘图Turtle库
2019/10/12 Python
用python实现名片管理系统
2020/06/18 Python
Keras - GPU ID 和显存占用设定步骤
2020/06/22 Python
JAKO-O德国野酷台湾站:德国首屈一指的婴幼童用品品牌
2019/01/14 全球购物
英国家居用品和家居装饰品购物网站:Cox & Cox
2019/08/25 全球购物
临床医学专业个人的自我评价
2013/09/27 职场文书
现场施工员岗位职责
2014/03/10 职场文书
工程材料采购方案
2014/05/18 职场文书
装修活动策划方案
2014/08/27 职场文书
街道党工委党的群众路线教育实践活动对照检查材料思想汇报
2014/10/05 职场文书
小学生勤俭节约倡议书
2015/04/29 职场文书
个人工作总结怎么写?
2019/04/09 职场文书
Python利器openpyxl之操作excel表格
2021/04/17 Python
linux下安装redis图文详细步骤
2021/12/04 Redis