歡迎您光臨本站 註冊首頁

python將logging模塊封裝成單獨模塊並實現動態切換Level方式

←手機掃碼閱讀     ljg58026 @ 2020-05-13 , reply:0

查找了很多資料,但網上給出的教程都是大同小異的,而我想將代碼進一步精簡,解耦,想實現如下兩個目標
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:Myworkspacepythonlogging_modulelogging_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:Myworkspacepythonlogging_modulelogging_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:Myworkspacepythonlogging_modulelogging_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")


[ljg58026 ] python將logging模塊封裝成單獨模塊並實現動態切換Level方式已經有255次圍觀

http://coctec.com/docs/python/shhow-post-234324.html