logging模块(* * * * *)
一 (簡(jiǎn)單應(yīng)用)、
import logging logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message')輸出:
WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message
可見,默認(rèn)情況下Python的logging模塊將日志打印到了標(biāo)準(zhǔn)輸出中,且只顯示了大于等于WARNING級(jí)別的日志,這說明默認(rèn)的日志級(jí)別設(shè)置為WARNING(日志級(jí)別等級(jí)CRITICAL > ERROR > WARNING >?INFO > DEBUG > NOTSET),默認(rèn)的日志格式為日志級(jí)別:Logger名稱:用戶輸出消息。
二 ?靈活配置日志級(jí)別,日志格式,輸出位置
1 import logging 2 logging.basicConfig(level=logging.DEBUG, 3 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', 4 datefmt='%a, %d %b %Y %H:%M:%S', 5 filename='/tmp/test.log', 6 filemode='w') 7 8 logging.debug('debug message') 9 logging.info('info message') 10 logging.warning('warning message') 11 logging.error('error message') 12 logging.critical('critical message')查看輸出:
cat /tmp/test.log?
Mon, 05 May 2014 16:29:53 test_logging.py[line:9] DEBUG debug message
Mon, 05 May 2014 16:29:53 test_logging.py[line:10] INFO info message
Mon, 05 May 2014 16:29:53 test_logging.py[line:11] WARNING warning message
Mon, 05 May 2014 16:29:53 test_logging.py[line:12] ERROR error message
Mon, 05 May 2014 16:29:53 test_logging.py[line:13] CRITICAL critical message
可見在logging.basicConfig()函數(shù)中可通過具體參數(shù)來更改logging模塊默認(rèn)行為,可用參數(shù)有
filename:用指定的文件名創(chuàng)建FiledHandler(后邊會(huì)具體講解handler的概念),這樣日志會(huì)被存儲(chǔ)在指定的文件中。
filemode:文件打開方式,在指定了filename時(shí)使用這個(gè)參數(shù),默認(rèn)值為“a”還可指定為“w”。
format:指定handler使用的日志顯示格式。?
datefmt:指定日期時(shí)間格式。?
level:設(shè)置rootlogger(后邊會(huì)講解具體概念)的日志級(jí)別?
stream:用指定的stream創(chuàng)建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件(f=open('test.log','w')),默認(rèn)為sys.stderr。若同時(shí)列出了filename和stream兩個(gè)參數(shù),則stream參數(shù)會(huì)被忽略。
format參數(shù)中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 數(shù)字形式的日志級(jí)別
%(levelname)s 文本形式的日志級(jí)別
%(pathname)s 調(diào)用日志輸出函數(shù)的模塊的完整路徑名,可能沒有
%(filename)s 調(diào)用日志輸出函數(shù)的模塊的文件名
%(module)s 調(diào)用日志輸出函數(shù)的模塊名
%(funcName)s 調(diào)用日志輸出函數(shù)的函數(shù)名
%(lineno)d 調(diào)用日志輸出函數(shù)的語句所在的代碼行
%(created)f 當(dāng)前時(shí)間,用UNIX標(biāo)準(zhǔn)的表示時(shí)間的浮 點(diǎn)數(shù)表示
%(relativeCreated)d 輸出日志信息時(shí)的,自Logger創(chuàng)建以 來的毫秒數(shù)
%(asctime)s 字符串形式的當(dāng)前時(shí)間。默認(rèn)格式是 “2003-07-08 16:49:45,896”。逗號(hào)后面的是毫秒
%(thread)d 線程ID。可能沒有
%(threadName)s 線程名。可能沒有
%(process)d 進(jìn)程ID。可能沒有
%(message)s用戶輸出的消息
三 ?logger對(duì)象
? ??上述幾個(gè)例子中我們了解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分別用以記錄不同級(jí)別的日志信息),logging.basicConfig()(用默認(rèn)日志格式(Formatter)為日志系統(tǒng)建立一個(gè)默認(rèn)的流處理器(StreamHandler),設(shè)置基礎(chǔ)配置(如日志級(jí)別等)并加到root logger(根Logger)中)這幾個(gè)logging模塊級(jí)別的函數(shù),另外還有一個(gè)模塊級(jí)別的函數(shù)是logging.getLogger([name])(返回一個(gè)logger對(duì)象,如果沒有指定名字將返回root logger)
? ? ?先看一個(gè)最簡(jiǎn)單的過程:
1 import logging 2 3 logger = logging.getLogger() 4 # 創(chuàng)建一個(gè)handler,用于寫入日志文件 5 fh = logging.FileHandler('test.log') 6 7 # 再創(chuàng)建一個(gè)handler,用于輸出到控制臺(tái) 8 ch = logging.StreamHandler() 9 10 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 11 12 fh.setFormatter(formatter) 13 ch.setFormatter(formatter) 14 15 logger.addHandler(fh) #logger對(duì)象可以添加多個(gè)fh和ch對(duì)象 16 logger.addHandler(ch) 17 18 logger.debug('logger debug message') 19 logger.info('logger info message') 20 logger.warning('logger warning message') 21 logger.error('logger error message') 22 logger.critical('logger critical message')先簡(jiǎn)單介紹一下,logging庫(kù)提供了多個(gè)組件:Logger、Handler、Filter、Formatter。Logger對(duì)象提供應(yīng)用程序可直接使用的接口,Handler發(fā)送日志到適當(dāng)?shù)哪康牡?#xff0c;Filter提供了過濾日志信息的方法,Formatter指定日志顯示格式。
? ? ?(1)
? ? ? Logger是一個(gè)樹形層級(jí)結(jié)構(gòu),輸出信息之前都要獲得一個(gè)Logger(如果沒有顯示的獲取則自動(dòng)創(chuàng)建并使用root Logger,如第一個(gè)例子所示)。
? ? ? logger = logging.getLogger()返回一個(gè)默認(rèn)的Logger也即root Logger,并應(yīng)用默認(rèn)的日志級(jí)別、Handler和Formatter設(shè)置。
當(dāng)然也可以通過Logger.setLevel(lel)指定最低的日志級(jí)別,可用的日志級(jí)別有l(wèi)ogging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。
? ? ? Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()輸出不同級(jí)別的日志,只有日志等級(jí)大于或等于設(shè)置的日志級(jí)別的日志才會(huì)被輸出。?
只輸出了
2014-05-06 12:54:43,222 - root - WARNING - logger warning message
2014-05-06 12:54:43,223 - root - ERROR - logger error message
2014-05-06 12:54:43,224 - root - CRITICAL - logger critical message
? ? ?從這個(gè)輸出可以看出logger = logging.getLogger()返回的Logger名為root。這里沒有用logger.setLevel(logging.Debug)顯示的為logger設(shè)置日志級(jí)別,所以使用默認(rèn)的日志級(jí)別WARNIING,故結(jié)果只輸出了大于等于WARNIING級(jí)別的信息。
? ? ?(2) 如果我們?cè)賱?chuàng)建兩個(gè)logger對(duì)象:?
1 ################################################## 2 logger1 = logging.getLogger('mylogger') 3 logger1.setLevel(logging.DEBUG) 4 5 logger2 = logging.getLogger('mylogger') 6 logger2.setLevel(logging.INFO) 7 8 logger1.addHandler(fh) 9 logger1.addHandler(ch) 10 11 logger2.addHandler(fh) 12 logger2.addHandler(ch) 13 14 logger1.debug('logger1 debug message') 15 logger1.info('logger1 info message') 16 logger1.warning('logger1 warning message') 17 logger1.error('logger1 error message') 18 logger1.critical('logger1 critical message') 19 20 logger2.debug('logger2 debug message') 21 logger2.info('logger2 info message') 22 logger2.warning('logger2 warning message') 23 logger2.error('logger2 error message') 24 logger2.critical('logger2 critical message')結(jié)果:
這里有兩個(gè)個(gè)問題:
? ? ? <1>我們明明通過logger1.setLevel(logging.DEBUG)將logger1的日志級(jí)別設(shè)置為了DEBUG,為何顯示的時(shí)候沒有顯示出DEBUG級(jí)別的日志信息,而是從INFO級(jí)別的日志開始顯示呢?
? ? ? ?原來logger1和logger2對(duì)應(yīng)的是同一個(gè)Logger實(shí)例,只要logging.getLogger(name)中名稱參數(shù)name相同則返回的Logger實(shí)例就是同一個(gè),且僅有一個(gè),也即name與Logger實(shí)例一一對(duì)應(yīng)。在logger2實(shí)例中通過logger2.setLevel(logging.INFO)設(shè)置mylogger的日志級(jí)別為logging.INFO,所以最后logger1的輸出遵從了后來設(shè)置的日志級(jí)別。
? ? ? <2>為什么logger1、logger2對(duì)應(yīng)的每個(gè)輸出分別顯示兩次?
? ? ? ?這是因?yàn)槲覀兺ㄟ^logger = logging.getLogger()顯示的創(chuàng)建了root Logger,而logger1 = logging.getLogger('mylogger')創(chuàng)建了root Logger的孩子(root.)mylogger,logger2同樣。而孩子,孫子,重孫……既會(huì)將消息分發(fā)給他的handler進(jìn)行處理也會(huì)傳遞給所有的祖先Logger處理。
? ? ? ? ok,那么現(xiàn)在我們把
# logger.addHandler(fh)
# logger.addHandler(ch) ?注釋掉,我們?cè)賮砜葱Ч?#xff1a;
因?yàn)槲覀冏⑨屃薼ogger對(duì)象顯示的位置,所以才用了默認(rèn)方式,即標(biāo)準(zhǔn)輸出方式。因?yàn)樗母讣?jí)沒有設(shè)置文件顯示方式,所以在這里只打印了一次。
孩子,孫子,重孫……可逐層繼承來自祖先的日志級(jí)別、Handler、Filter設(shè)置,也可以通過Logger.setLevel(lel)、Logger.addHandler(hdlr)、Logger.removeHandler(hdlr)、Logger.addFilter(filt)、Logger.removeFilter(filt)。設(shè)置自己特別的日志級(jí)別、Handler、Filter。若不設(shè)置則使用繼承來的值。
<3>Filter
? ? ?限制只有滿足過濾規(guī)則的日志才會(huì)輸出。
? ? ?比如我們定義了filter = logging.Filter('a.b.c'),并將這個(gè)Filter添加到了一個(gè)Handler上,則使用該Handler的Logger中只有名字帶 ? ? ? ? ?a.b.c前綴的Logger才能輸出其日志。
?
? ? ?filter = logging.Filter('mylogger')?
? ? ?logger.addFilter(filter)
? ? ?這是只對(duì)logger這個(gè)對(duì)象進(jìn)行篩選
? ? ?如果想對(duì)所有的對(duì)象進(jìn)行篩選,則:
? ? ??filter = logging.Filter('mylogger')?
? ? ? fh.addFilter(filter)
? ? ? ch.addFilter(filter)
? ? ? 這樣,所有添加fh或者ch的logger對(duì)象都會(huì)進(jìn)行篩選。
完整代碼1:
1 import logging 2 3 logger = logging.getLogger() 4 # 創(chuàng)建一個(gè)handler,用于寫入日志文件 5 fh = logging.FileHandler('test.log') 6 7 # 再創(chuàng)建一個(gè)handler,用于輸出到控制臺(tái) 8 ch = logging.StreamHandler() 9 10 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 11 12 fh.setFormatter(formatter) 13 ch.setFormatter(formatter) 14 15 # 定義一個(gè)filter 16 filter = logging.Filter('mylogger') 17 fh.addFilter(filter) 18 ch.addFilter(filter) 19 20 # logger.addFilter(filter) 21 logger.addHandler(fh) 22 logger.addHandler(ch) 23 24 25 26 27 logger.setLevel(logging.DEBUG) 28 29 logger.debug('logger debug message') 30 logger.info('logger info message') 31 logger.warning('logger warning message') 32 logger.error('logger error message') 33 logger.critical('logger critical message') 34 35 ################################################## 36 logger1 = logging.getLogger('mylogger') 37 logger1.setLevel(logging.DEBUG) 38 39 logger2 = logging.getLogger('mylogger') 40 logger2.setLevel(logging.INFO) 41 42 logger1.addHandler(fh) 43 logger1.addHandler(ch) 44 45 logger2.addHandler(fh) 46 logger2.addHandler(ch) 47 48 logger1.debug('logger1 debug message') 49 logger1.info('logger1 info message') 50 logger1.warning('logger1 warning message') 51 logger1.error('logger1 error message') 52 logger1.critical('logger1 critical message') 53 54 logger2.debug('logger2 debug message') 55 logger2.info('logger2 info message') 56 logger2.warning('logger2 warning message') 57 logger2.error('logger2 error message') 58 logger2.critical('logger2 critical message') 1 #coding:utf-8 2 import logging 3 4 # 創(chuàng)建一個(gè)logger 5 logger = logging.getLogger() 6 7 logger1 = logging.getLogger('mylogger') 8 logger1.setLevel(logging.DEBUG) 9 10 logger2 = logging.getLogger('mylogger') 11 logger2.setLevel(logging.INFO) 12 13 logger3 = logging.getLogger('mylogger.child1') 14 logger3.setLevel(logging.WARNING) 15 16 logger4 = logging.getLogger('mylogger.child1.child2') 17 logger4.setLevel(logging.DEBUG) 18 19 logger5 = logging.getLogger('mylogger.child1.child2.child3') 20 logger5.setLevel(logging.DEBUG) 21 22 # 創(chuàng)建一個(gè)handler,用于寫入日志文件 23 fh = logging.FileHandler('/tmp/test.log') 24 25 # 再創(chuàng)建一個(gè)handler,用于輸出到控制臺(tái) 26 ch = logging.StreamHandler() 27 28 # 定義handler的輸出格式formatter 29 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 30 fh.setFormatter(formatter) 31 ch.setFormatter(formatter) 32 33 #定義一個(gè)filter 34 #filter = logging.Filter('mylogger.child1.child2') 35 #fh.addFilter(filter) 36 37 # 給logger添加handler 38 #logger.addFilter(filter) 39 logger.addHandler(fh) 40 logger.addHandler(ch) 41 42 #logger1.addFilter(filter) 43 logger1.addHandler(fh) 44 logger1.addHandler(ch) 45 46 logger2.addHandler(fh) 47 logger2.addHandler(ch) 48 49 #logger3.addFilter(filter) 50 logger3.addHandler(fh) 51 logger3.addHandler(ch) 52 53 #logger4.addFilter(filter) 54 logger4.addHandler(fh) 55 logger4.addHandler(ch) 56 57 logger5.addHandler(fh) 58 logger5.addHandler(ch) 59 60 # 記錄一條日志 61 logger.debug('logger debug message') 62 logger.info('logger info message') 63 logger.warning('logger warning message') 64 logger.error('logger error message') 65 logger.critical('logger critical message') 66 67 logger1.debug('logger1 debug message') 68 logger1.info('logger1 info message') 69 logger1.warning('logger1 warning message') 70 logger1.error('logger1 error message') 71 logger1.critical('logger1 critical message') 72 73 logger2.debug('logger2 debug message') 74 logger2.info('logger2 info message') 75 logger2.warning('logger2 warning message') 76 logger2.error('logger2 error message') 77 logger2.critical('logger2 critical message') 78 79 logger3.debug('logger3 debug message') 80 logger3.info('logger3 info message') 81 logger3.warning('logger3 warning message') 82 logger3.error('logger3 error message') 83 logger3.critical('logger3 critical message') 84 85 logger4.debug('logger4 debug message') 86 logger4.info('logger4 info message') 87 logger4.warning('logger4 warning message') 88 logger4.error('logger4 error message') 89 logger4.critical('logger4 critical message') 90 91 logger5.debug('logger5 debug message') 92 logger5.info('logger5 info message') 93 logger5.warning('logger5 warning message') 94 logger5.error('logger5 error message') 95 logger5.critical('logger5 critical message') 1 import os 2 import time 3 import logging 4 from config import settings 5 6 7 def get_logger(card_num, struct_time): 8 9 if struct_time.tm_mday < 23: 10 file_name = "%s_%s_%d" %(struct_time.tm_year, struct_time.tm_mon, 22) 11 else: 12 file_name = "%s_%s_%d" %(struct_time.tm_year, struct_time.tm_mon+1, 22) 13 14 file_handler = logging.FileHandler( 15 os.path.join(settings.USER_DIR_FOLDER, card_num, 'record', file_name), 16 encoding='utf-8' 17 ) 18 fmt = logging.Formatter(fmt="%(asctime)s : %(message)s") 19 file_handler.setFormatter(fmt) 20 21 logger1 = logging.Logger('user_logger', level=logging.INFO) 22 logger1.addHandler(file_handler) 23 return logger1原文鏈接:https://www.cnblogs.com/yuanchenqi/articles/5732581.html
轉(zhuǎn)載于:https://www.cnblogs.com/jiawen010/p/9917082.html
總結(jié)
以上是生活随笔為你收集整理的logging模块(* * * * *)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】java反射--注解
- 下一篇: css 学习记录