logging模塊
日志基礎(chǔ)
日志級(jí)別(從低到高):
logging.NOTSET:不設(shè)置
loging.debug:最詳細(xì)的日志信息爹袁,通常用于問(wèn)題診斷
logging.info:信息的詳細(xì)程度僅次于debug毅否,通常記錄關(guān)鍵節(jié)點(diǎn)的信息,用于確認(rèn)一別都是按照預(yù)期的那樣進(jìn)行工作
logging.warning:當(dāng)某些不期望的事情發(fā)生時(shí)記錄的信息(如评雌,磁盤可用空間較低)树枫,但是此時(shí)應(yīng)用程序還是正常運(yùn)行的
logging.error:由于一個(gè)更嚴(yán)重的問(wèn)題導(dǎo)致某些功能不能正常運(yùn)行時(shí)記錄的信息
logging.critical:致命錯(cuò)誤,導(dǎo)致程序不能繼續(xù)運(yùn)行時(shí)記錄的信息
注意:logging的默認(rèn)級(jí)別為warning
日志包含的內(nèi)容
事件發(fā)生的時(shí)間
事件發(fā)生的位置
事件的嚴(yán)重程度(日志的級(jí)別)
事件的內(nèi)容
logging模塊提供的兩種記錄日志的方式
使用logging提供的模塊級(jí)別的函數(shù)(其實(shí)也是對(duì)logging日志系統(tǒng)相關(guān)類的封裝而已)
使用logging日志系統(tǒng)的四大組件
logging模塊定義的模塊級(jí)別的常用函數(shù)
import logging
#創(chuàng)建不同嚴(yán)重級(jí)別的的日志記錄
logging.debug(msg, *args, **kwargs)
logging.info(msg, *args, **kwargs)
logging.warning(msg, *args, **kwargs)
logging.error(msg, *args, **kwargs)
logging.critical(msg, *args, **kwargs)
logging.log(level, *args, **kwargs) #創(chuàng)建一條嚴(yán)重級(jí)別為level的日志記錄
logging.basicConfig(**kwargs) #對(duì)root logger進(jìn)行一次性配置
`其中l(wèi)ogging.basicConig(**kwargs)函數(shù)用于指定“要記錄的日志級(jí)別”景东、“日志格式”砂轻、“日志輸出位置”、“日志文件的打開模式”等信息
logging.basicConfig()函數(shù)說(shuō)明
該方法用于為logging日志系統(tǒng)做一些基本配置斤吐,方法定義如下:
logging.basicConfig(**kwargs)
filename:指定日志輸出目標(biāo)文件的文件名搔涝,指定后日志內(nèi)容就不會(huì)輸出到控制臺(tái)
filemode:指定日志文件的打開模式,默認(rèn)為“a”曲初,即追加体谒。需要在指定filename時(shí)才有效
format:指定日志格式字符串,即指定日志輸出時(shí)所包含的字段信息以及他們的順序臼婆。
datefmt:dateformat的縮寫。指定日期/時(shí)間格式幌绍。需要在format中包含時(shí)間字段%(asctime)s時(shí)才有效
level:指定日志器的日志級(jí)別
stream:指定日志輸出目標(biāo)stream,如sys.stdout颁褂、sys.stderr以及網(wǎng)絡(luò)stream。stream和filename不能同時(shí)提供傀广,否則引發(fā)ValueError錯(cuò)誤
style:指定format格式字符串的風(fēng)格颁独,可取值為"%"、"{"伪冰、和"$"誓酒,默認(rèn)為"%"
handlers:該選項(xiàng)如果被指定,它應(yīng)該是一個(gè)創(chuàng)建了多個(gè)Handler的可迭代對(duì)象贮聂,這些handler將會(huì)被添加到root logger靠柑。filename、stream吓懈、handlers這三個(gè)配置只能有一個(gè)存在歼冰,否則引發(fā)ValueError異常
logging模塊定義的格式字符串(format參數(shù))字段
%(asctime)s:日志發(fā)生的時(shí)間,人類可讀時(shí)間耻警,如:2019-06-29
%(created)f:日志事件發(fā)生的時(shí)間——時(shí)間戳隔嫡,即調(diào)用time.time()函數(shù)返回的值
%(relativeCreated)d:日志事件發(fā)生的時(shí)間相對(duì)于logging模塊加載時(shí)間的相對(duì)毫秒數(shù)
%(msecs)d:日志事件發(fā)生的毫秒部分
%(levelname)s:該日志記錄的文字形式的日志級(jí)別(DEBUG,INFO,WARNING,ERROR,CRITICAL)
%(levelno)s:該日志記錄的數(shù)字形式的日志級(jí)別(10甸怕,20,30腮恩,40梢杭,50)
%(name)s:所使用的日志器的名稱,默認(rèn)是"root",因?yàn)槟J(rèn)使用的root logger
%(message)s:日志記錄的文本內(nèi)容秸滴,通過(guò)
msg % args
計(jì)算得到%(pathname)s:調(diào)用日志記錄函數(shù)的源碼文件的全部路徑
%(filename)s:pathname的文件名部分武契,包含文件后綴
%(module)s:filename的名稱部分,不包含后綴
%(lineno)d:調(diào)用日志記錄函數(shù)的源代碼所在的行號(hào)
%(funcName)s:調(diào)用日志記錄函數(shù)的函數(shù)名
%(process)d:進(jìn)程ID
%(processName)s:進(jìn)程名稱
%(thread)d:線程ID
%(threadName)s:線程名稱
其他說(shuō)明
logging.basicConfig()函數(shù)是一個(gè)一次性的簡(jiǎn)單配置工具缸榛,即:只有在第一次調(diào)用該函數(shù)時(shí)會(huì)起作用吝羞,后續(xù)再次調(diào)用該函數(shù)時(shí)完全不會(huì)產(chǎn)生任何操作,多次調(diào)用的設(shè)置不是累加操作
日志器(logger)是有層級(jí)關(guān)系的内颗,上面調(diào)用的logging模塊級(jí)別的函數(shù)所使用的日志器是RootLogger類的實(shí)例钧排,其名稱為“root”,處于日志器層級(jí)關(guān)系最頂層均澳,且以單例模式存在
如果要記錄的日志中包含變量數(shù)據(jù)恨溜,可使用一個(gè)格式字符串作為這個(gè)事件的描述信息(logging.debug、logging.info等函數(shù)的第一個(gè)參數(shù)),然后將變量數(shù)據(jù)作為第二個(gè)參數(shù)*args的值進(jìn)行傳遞找前,eg:logging.warning("%s is %d years old"%, "Tom",23)
-
logging.debug()糟袁、logging.info()等方法的定義中,除了msg和args參數(shù)外躺盛,還有一個(gè)**kwargs參數(shù)项戴,他們支持3個(gè)關(guān)鍵茲參數(shù):exc_info,stack_info槽惫,extra
exc_info:值為布爾類型周叮,如果為True,就會(huì)將異常信息添加到日志消息中界斜,如果沒(méi)有異常信息則添加None到日志信息中
stack_info:值為布爾類型仿耽,默認(rèn)為False,如果參數(shù)設(shè)置為True各薇,棧信息會(huì)被添加到日志信息中
extra:這是一個(gè)字典(dict)參數(shù)项贺,可以用來(lái)自定義消息格式所包含的字段,但是他的key不能與logging模塊定義的字段沖突
logging模塊的四大組件
loggers:提供應(yīng)用程序代碼直接使用的接口
handlers:用于將日志記錄發(fā)送到指定的目的位置
filters:提供更詳細(xì)的日志過(guò)濾功能峭判,用于決定哪些日志記錄將會(huì)被輸出(其他的日志了會(huì)被忽略)
formatters:控制日志信息的最終輸出格式
四大組件的關(guān)系:
日志器(logger)需要通過(guò)處理器(handler)將日志新出目標(biāo)位置开缎,如:文件、sys.stdout朝抖、網(wǎng)絡(luò)等
不同的處理器(handler)可以將日志輸出到不同的位置
日志器(logger)可以設(shè)置多個(gè)處理器(handler)將同一條日志記錄輸出到不同的位置
每個(gè)處理器(handler)都可以設(shè)置自己的過(guò)濾器(filter)實(shí)現(xiàn)日志過(guò)濾啥箭,從而只保留感興趣的日志
即:日志器(logger)是入口,真正干活兒的是處理器(handler)治宣,處理器(handler)還可以通過(guò)過(guò)濾器(filter)和格式器(formatter)對(duì)要輸出的日志內(nèi)容做過(guò)濾和格式化等處理操作
logging的使用
可以通過(guò)logging模塊定義的模塊級(jí)別的方法去完成簡(jiǎn)單的日志記錄
只有級(jí)別大于或等于日志記錄器指定級(jí)別的日志記錄才會(huì)被輸出急侥,小于該級(jí)別的日志記錄將會(huì) 被丟棄
logging日志模塊相關(guān)類及其常用方法介紹
- Logger類常用方法:
Logger.setLevel():設(shè)置日志器將會(huì)處理的日志消息的最低嚴(yán)重級(jí)別
Logger.addHandler()和Logger.removeHandler():為logger對(duì)象添加和移除一個(gè)handler對(duì)象
Logger.addFilter()和Logger.removeFilter():為logger對(duì)象添加一移除一個(gè)filter對(duì)象
logger對(duì)象配置完成后砌滞,可以使用下面的方法來(lái)創(chuàng)建日志記錄:
Logger.debug()、Logger.info()坏怪、Logger.warning()贝润、Logger.error()、Logger.critical():創(chuàng)建一個(gè)與其方法名對(duì)應(yīng)等級(jí)的日志記錄
Logger.exception():創(chuàng)建一個(gè)類似于Logger.error()的日志消息
Logger.log():需要獲取一個(gè)明確的日志level參數(shù)來(lái)創(chuàng)建一個(gè)日志記錄
如何得到一個(gè)Logger對(duì)象铝宵?:logging.getLogger(name = "root")打掘,如果以相同的name參數(shù)多次調(diào)用getLogger方法,將會(huì)返回指向同一個(gè)Logger對(duì)象的引用
關(guān)于logger的層級(jí)結(jié)構(gòu)與有效等級(jí)的說(shuō)明:
logger的名稱是一個(gè)以"."分割的層級(jí)結(jié)構(gòu)鹏秋,每個(gè)"."后面的logger都是"."前面的loggerd children尊蚁,例如:有一個(gè)名稱為foo的logger,foo.bar侣夷,foo.bar.baz都是foo的后代
logger有一個(gè)“有效等級(jí)(effective level)”的概念横朋。如果一個(gè)logger上沒(méi)有被明確設(shè)置一個(gè)level,那么該logger 會(huì)使用他parent的level百拓,root logger總是會(huì)有一個(gè)明確的level設(shè)置(默認(rèn)為warning)
child loggers在完成對(duì)耳垂處理后琴锭,默認(rèn)會(huì)將日志消息傳遞給他們的祖先loggers相關(guān)的handlers,因此衙传,我們不必為一個(gè)應(yīng)用程序中所使用的所有l(wèi)oggers定義和配置handlers决帖,只需要為一個(gè)頂層的logger配置handlers,然后按照需要?jiǎng)?chuàng)建child loggers就可足夠蓖捶。我們也可通過(guò)將一個(gè)logger的propagate屬性設(shè)置為False來(lái)關(guān)閉這種傳遞機(jī)制
- Handler類:
Handler對(duì)象的作用是(基于日志消息的level)將消息分發(fā)到handler指定的位置(文件地回、網(wǎng)絡(luò)、郵件)俊鱼。Logger對(duì)象可以通過(guò)addHandler來(lái)為自己添加0個(gè)或多個(gè)handler對(duì)象落君。如:一個(gè)應(yīng)用程序要想實(shí)現(xiàn)以下幾個(gè)日志需求:
把所有日志都發(fā)送到一個(gè)日志文件中
把所有嚴(yán)重級(jí)別大于等于error的日志發(fā)送到stdout(標(biāo)準(zhǔn)輸出)
把所有嚴(yán)重級(jí)別軟critical的日志發(fā)送到一個(gè)email郵件地址
這種場(chǎng)景就需要3個(gè)不同的handlers,每個(gè)handlers負(fù)責(zé)發(fā)送一個(gè)特定嚴(yán)重級(jí)別的日志到一個(gè)特定位置
hanlder常用配置方法:
Handler.setLevel():設(shè)置handler將會(huì)處理的日志消息的最低嚴(yán)重級(jí)別
Handler.setFormatter():為handler設(shè)置一個(gè)格式器對(duì)象
Handler.addFilter()和Handler.removeFilter():為handler添加和刪除一個(gè)過(guò)濾器對(duì)象
注意:應(yīng)用程序代碼不應(yīng)該直接實(shí)例化和使用Handler實(shí)例亭引。因?yàn)镠andler是一個(gè)基類,它只定義了所有handlers都應(yīng)該有的接口皮获,痛楚提供了一些子類可以直接使用或覆蓋的默認(rèn)行為焙蚓。
常用Handler:
logging.StreamHandler:將日志消息發(fā)送Stream,如:std.out,std,err或任何file-like對(duì)象
logging.FileHandler:將日志消息發(fā)送到磁盤文件洒宝,默認(rèn)情況下文件大小會(huì)無(wú)限增長(zhǎng)
logging.handlers.RotationFileHandler:將日志消息發(fā)送到磁盤购公,并支持日志文件按大小切割
logging.hanlders.TimedRotatingFileHandler:將日志消息發(fā)送到磁盤文件,并支持日志文件按時(shí)間切割
logging.handlers.HTTPHandler:將日志消息發(fā)送給一個(gè)指定的HTTP服務(wù)器
logging.handlers.SMTPHandler:將日志消息發(fā)送給一個(gè)指定的email地址
logging.NullHandler:該Handler會(huì)忽略error messages,通常被想使用logging的library開發(fā)者用來(lái)避免"No handlers could be found for logger xxx"信息的出現(xiàn)
- Formater類
Formater對(duì)象用于配置日志信息的最終順序雁歌、結(jié)構(gòu)和內(nèi)容宏浩。與logging.Handler基類不同的是,應(yīng)用代碼可以直接實(shí)化Formatter類靠瞎。另外比庄,如果你的應(yīng)用程序需要一些特殊的處理行為求妹,也可以實(shí)現(xiàn)一個(gè)Formatter的子類來(lái)完成
Formatter類的構(gòu)造方法定義如下:logging.Foratter.__init__(fmt=None, datefmt = None, style = '%')
fmt:指定消息格式化字符串,如果不制定該參數(shù)則默認(rèn)使用message的原始值
datefmt:指定日期格式字符串佳窑,默認(rèn):"%Y-%m-%d- %H:%M:%S"
style:可取值為"%`制恍、%{、$",如果不指定則默認(rèn)使用"%"
- Filter類
Filter可以被Handler和Logger用來(lái)做比level更細(xì)粒度的神凑、更復(fù)雜的過(guò)濾功能净神。Filter是一個(gè)過(guò)濾器基類,只允許某個(gè)logger層級(jí)下的日志事件通過(guò)過(guò)濾溉委。該類定義如下:
class logging.Filter(name = "")
filter(record)
比如鹃唯,一個(gè)filter實(shí)例化時(shí)傳遞的name參數(shù)值為"A.B",那么該filter實(shí)例將只允許名稱為類似如下規(guī)則的loggers產(chǎn)生的日志記錄通過(guò)過(guò)濾:"A.B","A.B.C",而名稱為"A.BB"的loggers產(chǎn)生的日志則會(huì)被過(guò)濾掉瓣喊。如果name的值為空字符串坡慌,則允許所有的日志事件通過(guò)過(guò)濾
filter方法用于具體控制傳遞的record記錄是否能通過(guò)過(guò)濾,如果該方法返回值為0型宝,表示不能通過(guò)過(guò)濾八匠,返回值非0表示可以通過(guò)過(guò)濾。
ps:如果有需要趴酣,也可以在filter(record)方法內(nèi)部改變?cè)搑ecord梨树,比如添加、刪除或修改一些屬性岖寞。
最簡(jiǎn)單的日志輸出
法一:
import logging
log_format = "%(asctime)s-%(levelname)s-%(message)s" #注意小括號(hào)及其后的s
date_formate = "%m-%d-%Y %H:%M:%S%p"
logging.basicConfig(level=logging.DEBUG,filename="test.log",
datefmt=date_formate,format=log_format)
#以不同的級(jí)別輸出
logging.debug("This is a debug...")
logging.info("This is a info...")
logging.warning("This is a warning...")
logging.error("This is a error...")
logging.critical("This is a critical...")
以上代碼在Test.log文件的輸出結(jié)果如下
06-29-2019 20:44:47PM-DEBUG-This is a debug...
06-29-2019 20:44:47PM-INFO-This is a info...
06-29-2019 20:44:47PM-WARNING-This is a warning...
06-29-2019 20:44:47PM-ERROR-This is a error...
06-29-2019 20:44:47PM-CRITICAL-This is a critical...
法二:
import logging
log_format = "%(asctime)s-%(levelname)s-%(message)s" #注意小括號(hào)及其后的s
date_formate = "%m-%d-%Y %H:%M:%S%p"
logging.basicConfig(level=logging.DEBUG) #從debug輸出抡四,由于沒(méi)有設(shè)置filename,所以從控制臺(tái)輸出
logging.log(logging.DEBUG,"This is a debug")
logging.log(logging.INFO,"This is a info")
logging.log(logging.WARNING,"This is a warning")
logging.log(logging.ERROR,"This is a error")
logging.log(logging.CRITICAL,"This is a critical")
控制臺(tái)輸出內(nèi)容如下:
DEBUG:root:This is a debug #日志級(jí)別:日志器名稱:日志內(nèi)容
INFO:root:This is a info
WARNING:root:This is a warning
ERROR:root:This is a error
CRITICAL:root:This is a critical
使用四大組件記錄日志
import logging
import logging.handlers
import datetime
logger = logging.getLogger("my_logger")
logger.setLevel(logging.DEBUG)
rf_handler = logging.handlers.TimedRotatingFileHandler("all.log", when="midnight", interval=1,
backupCount=7, atTime=datetime.time(0, 0, 0, 0))
rf_handler.setFormatter(logging.Formatter("%(asctime)s-%(levelname)s-%(message)s"))
f_handler = logging.FileHandler("error.log")
f_handler.setLevel(logging.ERROR)
f_handler.setFormatter(logging.Formatter("%(asctime)s-%(levelname)s-%(filename)s[:%(lineno)d]-%(message)s"))
logger.addHandler(rf_handler)
logger.addHandler(f_handler)
logger.debug("This is a debug...")
logger.info("This is a info...")
logger.warning("This is a warning...")
logger.error("This is a error...")
logger.critical("This is a critical...")
在all.log中的輸出內(nèi)容如下:
2019-06-30 15:32:21,707-DEBUG-This is a debug...
2019-06-30 15:32:21,707-INFO-This is a info...
2019-06-30 15:32:21,708-WARNING-This is a warning...
2019-06-30 15:32:21,708-ERROR-This is a error...
2019-06-30 15:32:21,708-CRITICAL-This is a critical...
在error.log中的輸出內(nèi)容如下:
2019-06-30 15:32:21,708-ERROR-python高級(jí)功能之日志處理.py[:135]-This is a error...
2019-06-30 15:32:21,708-CRITICAL-python高級(jí)功能之日志處理.py[:136]-This is a critical...