2.logging進階教程

2.1簡介

????????Logging庫采用模塊化方法并且提供了幾類組件,它們分別是loggers, handlers, filters, and formatters。

  • Loggers組件暴露出應用代碼能夠直接調(diào)用的接口。

  • Handlers組件把日志記錄(Logger組件創(chuàng)建的)發(fā)給合適的目標。

  • Filter組件提供一個更優(yōu)越的方式來決定輸出哪個日志記錄。

  • Formatters組件指定最終輸出的日志記錄的格式。
    ????????在一個LogRecord實例中缠导,事件日志信息會在loggers,handlers溉痢,filters和formatters四個組件中進行傳遞僻造。
    ????????通過調(diào)用Logger類實例的方法來執(zhí)行日志記錄(后面統(tǒng)稱為loggers)。每個實例都有一個名稱孩饼,并且它們在概念上以.作為分隔符髓削,排在命名空間層次結構之后。例如镀娶,一個名為‘scan’日志記錄器是‘scan.text’立膛,‘scan.html’和‘scan.pdf’記錄器的父集。Logger的名稱可以取你想要的,建議最好是能表明該記錄器所記錄的區(qū)域宝泵。
    ????????當命名日志器時有一個慣例好啰,就是去使用模塊級別的日志器(根據(jù)模塊命名)。每一個要記錄日志的模塊都可以按如下進行命名:

    logger = logging.getLogger(__name__)
    

????????這意味著logger的名稱是根據(jù)所追蹤的包/模塊進行命名的儿奶。這也能夠在查詢?nèi)罩拘畔r很方便的知道是哪個包/模塊所記錄的日志信息框往。
????????頂級層次的日志記錄器被稱為root logger。這些logger所使用的方法與root logger所調(diào)用的方法有著一樣的名字闯捎,都叫debug()椰弊, info()warning()隙券, error()critical()。這些功能和方法都具有相同的簽名闹司。root logger的名稱在輸出信息中是“root”娱仔。
????????當然,如果想將日志信息輸出到不同的位置游桩,這也很方便牲迫。軟件包中包含支持用于將日志消息寫入文件,HTTP GET / POST位置借卧,通過SMTP發(fā)送電子郵件盹憎,通用套接字,隊列或特定于操作系統(tǒng)的日志記錄機制(如syslog或Windows NT事件日志)铐刘。目標位置是由handler類來處理的陪每。如果你想一些特殊的需求,內(nèi)置的handler類也沒有提供镰吵,那么這時需要你自己創(chuàng)建handler類來處理檩禾。
????????默認情況下是不對任何日志消息設置目標位置的。你可以像基礎教程中的那樣疤祭,通過basicConfig()來設置目標位置(例如控制臺或文件)盼产。當你調(diào)用debug()info()勺馆,warning()戏售,error()critical()這些方法時,它們會檢測目標位置草穆。如果沒有設置灌灾,在委托給根記錄器來進行實際的消息輸出之前,它們會默認輸出到控制臺(sys.stderr)并且以默認的格式格式化輸出信息悲柱。
????????basicConfig()默認的輸出信息格式如下:

severity:logger name:message

????????你可以通過改變basicConfig()的format參數(shù)值來調(diào)整格式紧卒。有關如何構造格式字符串的所有選項,詳情見 Formatter Objects诗祸。

2.2日志記錄流程

????????在記錄事件信息時跑芳,loggers與handlers的處理流程如下圖所示:


logging_flow.png

2.2.1.Loggers

????????Logger對象有3個作用轴总。1.Logger對象對外提供了幾個方法,這樣應用程序能夠在運行時記錄消息博个。2.Logger對象根據(jù)消息的嚴重性(默認的過濾工具)或過濾對象來確定要處理的日志對象怀樟。3.Logger對象將相關的日志信息傳遞給所有感興趣的日志處理器。
????????Logger對象使用的最廣泛的方法分為兩類:配置和發(fā)送信息盆佣。
????????以下是最常見的用于配置的方法:

  • Logger.setLevel()指定將要處理的最低嚴重性的日志消息往堡,注意debug是嚴重級別最低的而critical是嚴重級別最高的。舉個例子共耍,如果嚴重級別設置為INFO虑灰,logger對象只會處理INFO, WARNING, ERRORCRITICAL消息并且會忽略DEBUG消息。
  • Logger.addHandler()Logger.removeHandler()從logger對象中添加和移除處理對象痹兜。
  • Logger.addFilter()Logger.removeFilter()從logger對象中添加和移除過濾對象穆咐。
    ????????你不需要每次創(chuàng)建一個Logger對象都調(diào)用這些方法。
    ????????一旦logger對象配置完成字旭,以下方法就能創(chuàng)建出日志消息:
  • Logger.debug(), Logger.info(), Logger.warning(), Logger.error()Logger.critical()所有這些方法都將創(chuàng)建日志信息以及對應其名字的嚴重等級对湃。這信息實際上是一個格式化的字符串,這字符串包含了標準的字符串替換語法如%s, %d, %f等等遗淳。這剩下的參數(shù)是一個對象列表用于替換日志信息中的占位符拍柒。關于參數(shù)**kwargs,日志方法只關心exc_info關鍵字的值屈暗,根據(jù)這個關鍵字來決定是否記錄異常信息拆讯。
  • Logger.exception()創(chuàng)建一個類似于Logger.error()方法的日志消息。這兩者之間的區(qū)別是Logger.exception()會有一個堆棧信息养叛。這個通常是由一個異常處理器進行調(diào)用往果。
  • Logger.log()將日志級別作為一個顯示參數(shù)。這個方法相比于上面的日志方法要相對冗余一铅,但是可以自定義設置日志級別陕贮。
    ????????getLogger()方法返回一個logger類實例的引用。通過name參數(shù)來指定該logger實例的名稱潘飘,如果沒有指定則命名為root肮之。名字是以句點分隔的層次結構。當多次調(diào)用getLogger()方法指定的名稱一樣時卜录,就會返回同一個對象的引用戈擒。在分層列表中較低的logger是列表中較高的logger的子項,舉個例子艰毒,有一個名為foo的logger筐高,那么名為foo.barfoo.bar.bazfoo.bam的logger都是foologger的子類。
    ????????logger類有一個等效級別的概念柑土。如果logger沒有顯示設置級別蜀肘,那么logger會沿用它父級的有效級別。如果父級沒找到稽屏,會在父級的父級中找扮宠,以此類推,直到找到一個有效的級別狐榔。根logger的有效級別為WARNING坛增。當執(zhí)行一個事件時,有效級別就是用于決定需不需要把事件傳遞給logger的處理器薄腻。
    ????????子logger會將消息傳播給父級相關的處理器收捣。由于這個特性,你不必為一個應用中的所有l(wèi)ogger進行定義和配置庵楷。只要你為頂級的logger配置處理程序并根據(jù)需要創(chuàng)建子logger就足夠了罢艾。

2.2.2.Handlers

????????Handler對象的作用是將合適的日志信息(基于日志信息的優(yōu)先級)轉發(fā)到handler指定位置。Logger對象能夠通過addHandler()方法來添加0個或多個handler對象嫁乘。有這樣一個示例場景昆婿,一個應用球碉,需要將所有的日志信息保存到日志文件中蜓斧,error級別的日志或更高級別的輸出到控制臺,critical級別的日志需要使用郵件提醒睁冬。這個場景需要三個不同的處理器挎春,每個處理器都負責將不同級別的日志信息發(fā)送到指定的位置。
????????標準庫中包含了許多處理器的類型(詳見Useful Handlers)豆拨。在這個教程中主要使用StreamHandlerFileHandler兩個處理器直奋。
????????handler類提供了一些方法供開發(fā)者使用。如果開發(fā)者準備使用內(nèi)置的處理器對象施禾,那么以下就是這些配置方法:

  • setLevel()用于指定處理器處理的最低級別脚线。logger對象中也有一個setLevel()方法,logger中的是指定哪些信息轉發(fā)給handle弥搞,而這里的指定哪些信息發(fā)送到指定位置邮绿。
  • setFormatter()選擇一個formatter對象供handler使用。
  • addFilter()removeFilter()分別是配置filter和移除filter對象攀例。

????????應用程序代碼不應直接實例化和使用Handler類船逮。相反,Handler類是一個基類粤铭,它定義了所有處理程序應具有的接口挖胃,并建立了子類可以使用的一些默認行為。

2.2.3.Formatters

????????Formatter對象將會配置日志消息的最終順序,結構和內(nèi)容酱鸭。與logging.Handler基類不同吗垮,應用程序代碼可以直接實例化formatter類,當然你有一些特殊的要求或行為凛辣,你可以編寫formatter類的子類抱既。formatter類的構造函數(shù)需要三個可選的參數(shù)——信息格式字符串,日期格式字符串和樣式字符串扁誓。
????????????????logging.Formatter.init(fmt=None, datefmt=None, style='%')
????????如果沒有設置信息格式字符串防泵,那么會使用默認的信息格式。如果沒有設置日期格式字符串蝗敢,默認的日期格式如下:

%Y-%m-%d %H:%M:%S

????????最后會加上毫秒數(shù)捷泞。style參數(shù)是%, ‘{’或‘$’中的一個。如果沒有指定其中的一個寿谴,那么默認將會使用‘%’锁右。如果style參數(shù)的值為‘%’,消息格式字符串就會使用%(<dictionary key>)s樣式的字符串進行替換讶泰。這些可能的鍵在LogRecord attributes羅列出來了咏瑟。如果style的值為‘{’,那么消息字符串的格式與str.format()保持一致痪署。如果style的值為‘$’码泞,那么消息格式字符串應該與string.Template.substitute()的格式保持一致。
????????接下來的信息格式字符串的含義是以可讀的時間格式狼犯,信息的嚴重級別和信息內(nèi)容的順序進行日志記錄:

'%(asctime)s - %(levelname)s - %(message)s'

2.2.4.Configuring Logging

程序配置logging有以下3種方式:

  • 明確使用python代碼創(chuàng)建loggers對象, handlers對象,和formatters對象并調(diào)用上面列出的配置方法進行配置余寥。
  • 創(chuàng)建一個日志配置文件并使用fileConfig()方法來讀取它。
  • 創(chuàng)建一個含有配置信息的字典悯森,再將該字典傳遞給dictConfig()方法宋舷。
    ????????有關最后兩個選項的參考文檔,詳見Configuration functions瓢姻。接下來的例子是使用python代碼簡單配置一個logger祝蝠,一個控制臺處理器和一個簡單的格式化類:
import logging

# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warning message')
logger.error('error message')
logger.critical('critical message')

????????執(zhí)行代碼,顯示如下:

$ python3 simple.py
2018-08-29 10:29:47,835 - simple_example - DEBUG - debug message
2018-08-29 10:29:47,835 - simple_example - INFO - info message
2018-08-29 10:29:47,836 - simple_example - WARNING - warning message
2018-08-29 10:29:47,836 - simple_example - ERROR - error message
2018-08-29 10:29:47,836 - simple_example - CRITICAL - critical message

????????以下的例子使用配置文件進行配置:

import logging
import logging.config

logging.config.fileConfig('logging.conf')
# create logger
logger = logging.getLogger('simpleExample')

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

????????以下是logging.conf文件:

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

????????輸出如下:

$ python3 simple_file.py
2018-08-29 11:09:08,217 - simpleExample - DEBUG - debug message
2018-08-29 11:09:08,217 - simpleExample - INFO - info message
2018-08-29 11:09:08,218 - simpleExample - WARNING - warning message
2018-08-29 11:09:08,218 - simpleExample - ERROR - error message
2018-08-29 11:09:08,218 - simpleExample - CRITICAL - critical message

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末幻碱,一起剝皮案震驚了整個濱河市绎狭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌收班,老刑警劉巖坟岔,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異摔桦,居然都是意外死亡社付,警方通過查閱死者的電腦和手機承疲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸥咖,“玉大人燕鸽,你說我怎么就攤上這事√淅保” “怎么了啊研?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鸥拧。 經(jīng)常有香客問我党远,道長,這世上最難降的妖魔是什么富弦? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任沟娱,我火速辦了婚禮,結果婚禮上腕柜,老公的妹妹穿的比我還像新娘济似。我一直安慰自己,他們只是感情好盏缤,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布砰蠢。 她就那樣靜靜地躺著,像睡著了一般唉铜。 火紅的嫁衣襯著肌膚如雪台舱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天打毛,我揣著相機與錄音柿赊,去河邊找鬼俩功。 笑死幻枉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的诡蜓。 我是一名探鬼主播熬甫,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蔓罚!你這毒婦竟也來了椿肩?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤豺谈,失蹤者是張志新(化名)和其女友劉穎郑象,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茬末,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡厂榛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年盖矫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片击奶。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡辈双,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出柜砾,到底是詐尸還是另有隱情湃望,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布痰驱,位于F島的核電站证芭,受9級特大地震影響,放射性物質發(fā)生泄漏担映。R本人自食惡果不足惜檩帐,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望另萤。 院中可真熱鬧湃密,春花似錦、人聲如沸四敞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忿危。三九已至达箍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間铺厨,已是汗流浹背缎玫。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留解滓,地道東北人赃磨。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像洼裤,于是被迫代替她去往敵國和親邻辉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容

  • From:Python之日志處理(logging模塊) - 云游道士 - 博客園 https://www.cnbl...
    vigny的先生閱讀 2,684評論 3 5
  • 本文章是我大概三年前腮鞍,在上家單位使用 Python 工作時結合官方文檔做的整理≈岛В現(xiàn)在 Python 官方文檔聽說已...
    好吃的野菜閱讀 216,901評論 14 232
  • 本文翻譯自logging howto 基礎教程 日志是跟蹤軟件運行時發(fā)生事件的一種手段。Python開發(fā)者在代碼中...
    大蟒傳奇閱讀 4,254評論 0 17
  • 禾谷移国, 今天是馬不停蹄的一天吱瘩,上午英語課,下午提前去畫畫迹缀,然后再趕去參加信息杯比賽使碾。比賽出來你的第一句話是抱著我說...
    草馬束木閱讀 155評論 0 0
  • 永久的黑暗皱卓, 那是無邊的默然…… 猛然的一驚, 應是重生的必然部逮。 從此無眠…… 我抱著生的希望堅持娜汁、堅持, 懷著死...
    行者無疆87閱讀 646評論 0 50