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中类的继承代码实例
Oct 28 Python
Python通过90行代码搭建一个音乐搜索工具
Jul 29 Python
Python实现的朴素贝叶斯分类器示例
Jan 06 Python
python使用tensorflow保存、加载和使用模型的方法
Jan 31 Python
flask框架中勾子函数的使用详解
Aug 01 Python
Python OpenCV 使用滑动条来调整函数参数的方法
Jul 08 Python
python自动化UI工具发送QQ消息的实例
Aug 27 Python
keras打印loss对权重的导数方式
Jun 10 Python
Python 实现自动登录+点击+滑动验证功能
Jun 10 Python
利用python Pandas实现批量拆分Excel与合并Excel
May 23 Python
python爬取网页版QQ空间,生成各类图表
Jun 02 Python
python非标准时间的转换
Jul 25 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
索尼SONY SRF-S83/84电路分析和打磨
2021/03/02 无线电
Nigma vs Alliance BO5 第五场2.14
2021/03/10 DOTA
jQuery实现鼠标选中文字后弹出提示窗口效果【附demo源码】
2016/09/05 Javascript
JQuery ZTree使用方法详解
2017/01/07 Javascript
js实现拖拽上传图片功能
2017/08/01 Javascript
vue.js组件vue-waterfall-easy实现瀑布流效果
2017/08/22 Javascript
bootstrap可编辑下拉框jquery.editable-select
2017/10/12 jQuery
js实现随机抽奖
2020/03/19 Javascript
在react中使用vue的状态管理的方法示例
2020/05/02 Javascript
vue 解决addRoutes多次添加路由重复的操作
2020/08/04 Javascript
Express 配置HTML页面访问的实现
2020/11/01 Javascript
利用一个简单的例子窥探CPython内核的运行机制
2015/03/30 Python
Python两个内置函数 locals 和globals(学习笔记)
2016/08/28 Python
浅析Git版本控制器使用
2017/12/10 Python
如何利用python查找电脑文件
2018/04/27 Python
Python实现查找数组中任意第k大的数字算法示例
2019/01/23 Python
Python写一个基于MD5的文件监听程序
2019/03/11 Python
python爬虫 批量下载zabbix文档代码实例
2019/08/21 Python
Python插入Elasticsearch操作方法解析
2020/01/19 Python
python实现图像全景拼接
2020/03/27 Python
普通院校学生的自荐信
2013/11/27 职场文书
班组长安全生产职责
2013/12/16 职场文书
无工作经验者个人求职信范文
2013/12/22 职场文书
募捐倡议书怎么写
2014/05/14 职场文书
体育比赛口号
2014/06/09 职场文书
实验室的标语
2014/06/20 职场文书
大学生心理活动总结
2014/07/04 职场文书
2014年最新党员对照检查材料汇总
2014/09/15 职场文书
党的群众路线教育实践活动对照检查材料思想汇报
2014/09/19 职场文书
文员转正自我鉴定怎么写
2014/09/29 职场文书
报到证办理个人委托书
2014/10/06 职场文书
2014年大班保育员工作总结
2014/12/02 职场文书
2016春节家属慰问信
2015/03/25 职场文书
2016年先进教师个人事迹材料
2016/02/26 职场文书
求职自荐信该如何书写?
2019/06/24 职场文书
解决Mysql中的innoDB幻读问题
2022/04/29 MySQL