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 相关文章推荐
wxPython事件驱动实例详解
Sep 28 Python
DJANGO-ALLAUTH社交用户系统的安装配置
Nov 18 Python
将Emacs打造成强大的Python代码编辑工具
Nov 20 Python
Python基本语法经典教程
Mar 11 Python
Python调用ctypes使用C函数printf的方法
Aug 23 Python
你眼中的Python大牛 应该都有这份书单
Oct 31 Python
python的exec、eval使用分析
Dec 11 Python
使用Python进行AES加密和解密的示例代码
Feb 02 Python
python生成器推导式用法简单示例
Oct 08 Python
Python3标准库glob文件名模式匹配的问题
Mar 13 Python
python自动化操作之动态验证码、滑动验证码的降噪和识别
Aug 30 Python
Golang Web 框架Iris安装部署
Aug 14 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
桌面中心(一)创建数据库
2006/10/09 PHP
php截取中文字符串不乱码的方法
2013/12/25 PHP
PHP实现的XML操作类【XML Library】
2016/12/29 PHP
基于jquery实现的类似百度搜索的输入框自动完成功能
2011/08/23 Javascript
复制js对象方法(详解)
2013/07/08 Javascript
用js代码改变单选框选中状态的简单实例
2013/12/18 Javascript
jQuery fadeOut 异步实例代码详解
2016/08/18 Javascript
编写React组件项目实践分析
2018/03/04 Javascript
JavaScript代码实现txt文件的上传预览功能
2018/03/27 Javascript
Vue 项目分环境打包的方法示例
2018/08/03 Javascript
dts文件中删除一个node或属性的操作方法
2018/08/05 Javascript
JavaScript展开操作符(Spread operator)详解
2019/07/20 Javascript
微信小程序官方动态自定义底部tabBar的例子
2019/09/04 Javascript
js实现轮播图特效
2020/05/28 Javascript
python基于multiprocessing的多进程创建方法
2015/06/04 Python
python使用fcntl模块实现程序加锁功能示例
2017/06/23 Python
Python cookbook(数据结构与算法)实现查找两个字典相同点的方法
2018/02/18 Python
Python实现的建造者模式示例
2018/08/06 Python
Python字符串处理的8招秘籍(小结)
2019/08/13 Python
关于django python manage.py startapp 应用名出错异常原因解析
2020/12/15 Python
Python环境搭建过程从安装到Hello World
2021/02/05 Python
蔻驰美国官网:COACH美国
2016/08/18 全球购物
Otticanet美国:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
俄罗斯一家时尚女装商店:Charuel
2019/12/04 全球购物
电气工程及其自动化学生实习自我鉴定
2013/09/19 职场文书
幼儿园老师辞职信
2014/01/20 职场文书
化学教学随笔感言
2014/02/19 职场文书
车间机修工岗位职责
2014/02/28 职场文书
电视购物广告词
2014/03/19 职场文书
高职教师先进事迹材料
2014/08/24 职场文书
医生学习党的群众路线教育实践活动心得体会
2014/11/03 职场文书
SONY AN-LP1 短波有源天线放大器
2021/04/22 无线电
浅谈react useEffect闭包的坑
2021/06/08 Javascript
Python如何解决secure_filename对中文不支持问题
2021/07/16 Python
使用Java去实现超市会员管理系统
2022/03/18 Java/Android
MySQL视图概念以及相关应用
2022/04/19 MySQL