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 控制语句
Nov 03 Python
python获取外网IP并发邮件的实现方法
Oct 01 Python
Django 跨域请求处理的示例代码
May 02 Python
windows下搭建python scrapy爬虫框架步骤
Dec 23 Python
python爬虫获取小区经纬度以及结构化地址
Dec 30 Python
Python redis操作实例分析【连接、管道、发布和订阅等】
May 16 Python
Django如何开发简单的查询接口详解
May 17 Python
Python批量生成幻影坦克图片实例代码
Jun 04 Python
用OpenCV将视频分解成单帧图片,图片合成视频示例
Dec 10 Python
Python super()函数使用及多重继承
May 06 Python
用pandas划分数据集实现训练集和测试集
Jul 20 Python
Scrapy 配置动态代理IP的实现
Sep 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
WordPress迁移时一些常见问题的解决方法整理
2015/11/24 PHP
详解PHP的Yii框架中的Controller控制器
2016/03/29 PHP
PHP生成随机数的方法总结
2018/03/01 PHP
jquery 元素相对定位代码
2010/10/15 Javascript
jquery iframe操作详细解析
2013/11/20 Javascript
深入分析Javascript跨域问题
2015/04/17 Javascript
js实现点击链接后延迟3秒再跳转的方法
2015/06/05 Javascript
Bootstrap进度条组件知识详解
2016/05/01 Javascript
JavaScript数据类型学习笔记分享
2016/09/01 Javascript
Easyui笔记2:实现datagrid多行删除的示例代码
2017/01/14 Javascript
js求数组中全部数字可拼接出的最大整数示例代码
2017/08/25 Javascript
浅谈Node Inspector 代理实现
2017/10/19 Javascript
JavaScript模拟实现封装的三种方式及写法区别
2017/10/27 Javascript
jquery如何实现点击空白处隐藏元素
2017/12/05 jQuery
JavaScript Array.flat()函数用法解析
2020/09/02 Javascript
JavaScript中EventBus实现对象之间通信
2020/10/18 Javascript
Python正则表达式教程之三:贪婪/非贪婪特性
2017/03/02 Python
Centos 升级到python3后pip 无法使用的解决方法
2018/06/12 Python
pyqt5 获取显示器的分辨率的方法
2019/06/18 Python
英国二手iPhone、音乐、电影和游戏商店:musicMagpie
2018/10/26 全球购物
含精油的天然有机化妆品:Indemne
2019/08/27 全球购物
乌克兰在线电子产品商店:MTA
2019/11/14 全球购物
实现向右循环移位
2014/07/31 面试题
大专应届生个人的自我评价
2013/11/21 职场文书
致长跑运动员加油稿
2014/02/20 职场文书
服务之星事迹材料
2014/05/03 职场文书
小区推广策划方案
2014/06/06 职场文书
公司离职证明样本
2014/09/13 职场文书
武夷山导游词
2015/02/03 职场文书
信贷客户经理岗位职责
2015/04/09 职场文书
小王子读书笔记
2015/06/29 职场文书
2016党员三严三实心得体会
2016/01/15 职场文书
Python提取PDF指定内容并生成新文件
2021/06/09 Python
pycharm部署django项目到云服务器的详细流程
2021/06/29 Python
关于CentOS 8 搭建MongoDB4.4分片集群的问题
2021/10/24 MongoDB
postgresql中如何执行sql文件
2023/05/08 PostgreSQL