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过滤函数filter()使用自定义函数过滤序列实例
Aug 26 Python
python连接oracle数据库实例
Oct 17 Python
介绍Python中的一些高级编程技巧
Apr 02 Python
深入理解python中函数传递参数是值传递还是引用传递
Nov 07 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
Nov 09 Python
详解小白之KMP算法及python实现
Apr 04 Python
Python3+OpenCV2实现图像的几何变换(平移、镜像、缩放、旋转、仿射)
May 13 Python
PyTorch的自适应池化Adaptive Pooling实例
Jan 03 Python
Python模块 _winreg操作注册表
Feb 05 Python
深入理解Python 多线程
Jun 16 Python
Python之字典对象的几种创建方法
Sep 30 Python
Python实现机器学习算法的分类
Jun 03 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
Linux下ZendOptimizer的安装与配置方法
2007/04/12 PHP
解析php如何将日志写进syslog
2013/06/28 PHP
yii2.0之GridView自定义按钮和链接用法
2014/12/15 PHP
PHP实现文件上传与下载实例与总结
2016/03/13 PHP
PHP实现文件下载【实例分享】
2017/04/28 PHP
JavaScript 字符串连接性能优化
2008/12/20 Javascript
js 鼠标拖动对象 可让任何div实现拖动效果
2009/11/09 Javascript
关于Aptana Studio生成自动备份文件的解决办法
2009/12/23 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
2012/12/23 Javascript
jquery ui对话框实例代码
2013/05/10 Javascript
IE、FF、Chrome浏览器中的JS差异介绍
2013/08/13 Javascript
返回顶部按钮响应滚动且动态显示与隐藏
2014/10/14 Javascript
node.js开发中使用Node Supervisor实现监测文件修改并自动重启应用
2014/11/04 Javascript
JS实现的自定义显示加载等待图片插件(loading.gif)
2016/06/17 Javascript
js仿支付宝多方框输入支付密码效果
2016/09/27 Javascript
NodeJS学习笔记之Module的简介
2017/03/24 NodeJs
React Native 搭建开发环境的方法步骤
2017/10/30 Javascript
jQuery实现带右侧索引功能的通讯录示例【附源码下载】
2018/04/17 jQuery
nodejs实现的http、https 请求封装操作示例
2020/02/06 NodeJs
JavaScript函数重载操作实例浅析
2020/05/02 Javascript
用Angular实现一个扫雷的游戏示例
2020/05/15 Javascript
TensorFlow利用saver保存和提取参数的实例
2018/07/26 Python
详解PyCharm配置Anaconda的艰难心路历程
2018/08/13 Python
python实现本地图片转存并重命名的示例代码
2018/10/27 Python
django-crontab 定时执行任务方法的实现
2019/09/06 Python
Django1.11配合uni-app发起微信支付的实现
2019/10/12 Python
python运用pygame库实现双人弹球小游戏
2019/11/25 Python
如何基于Python创建目录文件夹
2019/12/31 Python
Python 列表中的修改、添加和删除元素的实现
2020/06/11 Python
巴基斯坦购物网站:Goto
2019/03/11 全球购物
公司员工检讨书
2014/02/08 职场文书
党员评议个人总结
2014/10/20 职场文书
艺术节开幕词
2015/01/28 职场文书
任命通知范文
2015/04/21 职场文书
社区禁毒宣传活动总结
2015/05/07 职场文书
劳动仲裁撤诉申请书
2015/05/18 职场文书