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实现的jpg格式图片修复代码
Apr 21 Python
Python使用pip安装pySerial串口通讯模块
Apr 20 Python
Python3.6基于正则实现的计算器示例【无优化简单注释版】
Jun 14 Python
pycharm在调试python时执行其他语句的方法
Nov 29 Python
selenium+python设置爬虫代理IP的方法
Nov 29 Python
python解析yaml文件过程详解
Aug 30 Python
Python列表删除元素del、pop()和remove()的区别小结
Sep 11 Python
Python通过Manager方式实现多个无关联进程共享数据的实现
Nov 07 Python
Django+python服务器部署与环境部署教程详解
Mar 30 Python
tensorflow 大于某个值为1,小于为0的实例
Jun 30 Python
基于Python实现全自动下载抖音视频
Nov 06 Python
python 远程执行命令的详细代码
Feb 15 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之第六天
2006/10/09 PHP
php4的彩蛋
2006/10/09 PHP
php将字符串随机分割成不同长度数组的方法
2015/06/01 PHP
解读PHP的Yii框架中请求与响应的处理流程
2016/03/17 PHP
Yii数据库缓存实例分析
2016/03/29 PHP
php解析mht文件转换成html的实例
2017/03/13 PHP
php生成word并下载代码实例
2019/03/15 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
学习ExtJS(一) 之基础前提
2009/10/07 Javascript
js和jquery批量绑定事件传参数一(新猪猪原创)
2010/06/23 Javascript
ie6下png图片背景不透明的解决办法使用js实现
2013/01/11 Javascript
解决json日期格式问题的3种方法
2014/02/02 Javascript
JS数组的遍历方式for循环与for...in
2014/07/31 Javascript
jquery使用slideDown实现模块缓慢拉出效果的方法
2015/03/27 Javascript
jQuery实现多级下拉菜单jDropMenu的方法
2015/08/28 Javascript
记一次webpack3升级webpack4的踩坑经历
2018/06/12 Javascript
详解webpack模块加载器兼打包工具
2018/09/11 Javascript
微信小程序 scroll-view 水平滚动实现过程解析
2019/10/12 Javascript
9个JavaScript日常开发小技巧
2020/10/06 Javascript
[51:26]VP vs VG 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python3+pyqt5+itchat微信定时发送消息的方法
2019/02/20 Python
Python简易版图书管理系统
2019/08/12 Python
Anaconda3+tensorflow2.0.0+PyCharm安装与环境搭建(图文)
2020/02/18 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
2020/04/12 Python
Python实现清理微信僵尸粉功能示例【基于itchat模块】
2020/05/29 Python
Web前端页面跳转并取到值
2017/04/24 HTML / CSS
H5页面适配iPhoneX(就是那么简单)
2019/12/02 HTML / CSS
英国索普公园票务和酒店套餐:Thorpe Breaks
2019/09/14 全球购物
早晨薰衣草在线女性精品店:Morning Lavender
2021/01/04 全球购物
什么是唯一索引
2015/07/05 面试题
汇源肾宝广告词
2014/03/20 职场文书
《春天来了》教学反思
2014/04/07 职场文书
质量管理标语
2014/06/12 职场文书
计划生育工作总结2015
2015/04/03 职场文书
婚庆开业庆典主持词
2015/06/30 职场文书
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript