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简单的实现树莓派的WEB控制
Feb 18 Python
Python实现连接两个无规则列表后删除重复元素并升序排序的方法
Feb 05 Python
Python读取视频的两种方法(imageio和cv2)
Apr 15 Python
对python修改xml文件的节点值方法详解
Dec 24 Python
python3.x实现base64加密和解密
Mar 28 Python
python项目对接钉钉SDK的实现
Jul 15 Python
解决python tkinter界面卡死的问题
Jul 17 Python
解决python 文本过滤和清理问题
Aug 28 Python
Django中使用Json返回数据的实现方法
Jun 03 Python
keras实现VGG16 CIFAR10数据集方式
Jul 07 Python
Python3爬虫关于代理池的维护详解
Jul 30 Python
python3.8.3安装教程及环境配置的详细教程(64-bit)
Nov 28 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简单实现多字节字符串翻转的方法
2015/03/31 PHP
PHP使用数组依次替换字符串中匹配项
2016/01/08 PHP
如何用PHP做到页面注册审核
2017/03/02 PHP
js根据给定的日期计算当月有多少天实现思路及代码
2013/02/25 Javascript
jQuery布局插件UI Layout简介及使用方法
2013/04/03 Javascript
JS中的substring和substr函数的区别说明
2013/05/07 Javascript
javascript删除数组重复元素的方法汇总
2015/06/24 Javascript
JavaScript实现动态删除列表框值的方法
2015/08/12 Javascript
jquery.validate 自定义验证方法及validate相关参数
2016/01/18 Javascript
nodejs修复ipa处理过的png图片
2016/02/17 NodeJs
原生js仿jquery一些常用方法(必看篇)
2016/09/20 Javascript
js处理层级数据结构的方法小结
2017/01/17 Javascript
详解JavaScript对象的深浅复制
2017/03/30 Javascript
jQuery中clone()函数实现表单中增加和减少输入项
2017/05/13 jQuery
JS实现简易换图时钟功能分析
2018/01/04 Javascript
element中el-container容器与div布局区分详解
2020/05/13 Javascript
解决vue watch数据的方法被调用了两次的问题
2020/11/07 Javascript
Python使用Tkinter实现机器人走迷宫
2018/01/22 Python
Python paramiko模块的使用示例
2018/04/11 Python
python中实现将多个print输出合成一个数组
2018/04/19 Python
python学生信息管理系统(完整版)
2020/04/05 Python
selenium设置proxy、headers的方法(phantomjs、Chrome、Firefox)
2018/11/29 Python
python ddt数据驱动最简实例代码
2019/02/22 Python
python使用phoenixdb操作hbase的方法示例
2019/02/28 Python
在Python中使用Neo4j的方法
2019/03/14 Python
快速解决vue.js 模板和jinja 模板冲突的问题
2019/07/26 Python
详解Python图像处理库Pillow常用使用方法
2019/09/02 Python
Laura官网:加拿大女性的顶级时尚目的地
2019/09/20 全球购物
俄罗斯品牌服装和鞋子在线商店:BRIONITY
2020/03/26 全球购物
商务日语毕业生自荐信
2013/11/23 职场文书
酒店拾金不昧表扬信
2014/01/18 职场文书
2014公安机关纪律作风整顿思想汇报
2014/09/13 职场文书
2014年防汛工作总结
2014/12/08 职场文书
小学信息技术教学反思
2016/02/16 职场文书
Python学习之包与模块详解
2022/03/19 Python
ubuntu安装jupyter并设置远程访问的实现
2022/03/31 Python