python logging模塊

基本介紹

  • logging提供的模塊級(jí)別的函數(shù)記錄日志
  • 日志級(jí)別: DEBUG < INFO < WARNING < ERROR < CRITICAL
  • 可以通過(guò)logging模塊定義的模塊級(jí)別的方法去完成簡(jiǎn)單的日志記錄
  • 只有級(jí)別大于或等于日志記錄器指定級(jí)別的日志記錄才會(huì)被輸出,小于該級(jí)別的日志記錄將會(huì)被丟棄蚓让。
  1. 最簡(jiǎn)單的日志輸出
    先來(lái)試著分別輸出一條不同日志級(jí)別的日志記錄:
import logging

logging.debug("This is a debug log.")
logging.info("This is a info log.")
logging.warning("This is a warning log.")
logging.error("This is a error log.")
logging.critical("This is a critical log.")

也可以這樣寫:

logging.log(logging.DEBUG, "This is a debug log.")
logging.log(logging.INFO, "This is a info log.")
logging.log(logging.WARNING, "This is a warning log.")
logging.log(logging.ERROR, "This is a error log.")
logging.log(logging.CRITICAL, "This is a critical log.")

輸出結(jié)果:

WARNING:root:This is a warning log.
ERROR:root:This is a error log.
CRITICAL:root:This is a critical log.
  1. 那么問(wèn)題來(lái)了
    問(wèn)題1:為什么前面兩條日志沒(méi)有被打印出來(lái)项棠?
    這是因?yàn)閘ogging模塊提供的日志記錄函數(shù)所使用的日志器設(shè)置的日志級(jí)別是WARNING昌跌,因此只有WARNING級(jí)別的日志記錄以及大于它的ERROR和CRITICAL級(jí)別的日志記錄被輸出了去件,而小于它的DEBUG和INFO級(jí)別的日志記錄被丟棄了。

    問(wèn)題2:打印出來(lái)的日志信息中各字段表示什么意思必孤?為什么會(huì)這樣輸出蓖救?
    上面輸出結(jié)果中每行日志記錄的各個(gè)字段含義分別是:

    日志級(jí)別:日志器名稱:日志內(nèi)容
    之所以會(huì)這樣輸出,是因?yàn)閘ogging模塊提供的日志記錄函數(shù)所使用的日志器設(shè)置的日志格式默認(rèn)是BASIC_FORMAT旧困,其值為:"%(levelname)s:%(name)s:%(message)s"

    問(wèn)題3:如果將日志記錄輸出到文件中醇份,而不是打印到控制臺(tái)稼锅?
    因?yàn)樵趌ogging模塊提供的日志記錄函數(shù)所使用的日志器設(shè)置的處理器所指定的日志輸出位置默認(rèn)為:
    sys.stderr。

    問(wèn)題4:我是怎么知道這些的僚纷?
    查看這些日志記錄函數(shù)的實(shí)現(xiàn)代碼矩距,可以發(fā)現(xiàn):當(dāng)我們沒(méi)有提供任何配置信息的時(shí)候,這些函數(shù)都會(huì)去調(diào)用logging.basicConfig(**kwargs)方法怖竭,且不會(huì)向該方法傳遞任何參數(shù)锥债。繼續(xù)查看basicConfig()方法的代碼就可以找到上面這些問(wèn)題的答案了。

    問(wèn)題5:怎么修改這些默認(rèn)設(shè)置呢痊臭?
    其實(shí)很簡(jiǎn)單哮肚,在我們調(diào)用上面這些日志記錄函數(shù)之前,手動(dòng)調(diào)用一下basicConfig()方法广匙,把我們想設(shè)置的內(nèi)容以參數(shù)的形式傳遞進(jìn)去就可以了允趟。

  2. logging.basicConfig()函數(shù)說(shuō)明
    該方法用于為logging日志系統(tǒng)做一些基本配置,方法定義如下:

logging.basicConfig(**kwargs)

該函數(shù)可接收的關(guān)鍵字參數(shù)如下:

參數(shù)名稱 | 描述

| -
filename | 指定日志輸出目標(biāo)文件的文件名鸦致,指定該設(shè)置項(xiàng)后日志信心就不會(huì)被輸出到控制臺(tái)了
filemode | 指定日志文件的打開(kāi)模式潮剪,默認(rèn)為'a'。需要注意的是分唾,該選項(xiàng)要在filename指定時(shí)才有效
format | 指定日志格式字符串抗碰,即指定日志輸出時(shí)所包含的字段信息以及它們的順序。logging模塊定義的格式字段下面會(huì)列出鳍寂。
datefmt | 指定日期/時(shí)間格式改含。需要注意的是,該選項(xiàng)要在format中包含時(shí)間字段%(asctime)s時(shí)才有效
level | 指定日志器的日志級(jí)別
stream | 指定日志輸出目標(biāo)stream迄汛,如sys.stdout捍壤、sys.stderr以及網(wǎng)絡(luò)stream。需要說(shuō)明的是鞍爱,stream和filename不能同時(shí)提供鹃觉,否則會(huì)引發(fā) ValueError異常
style | Python 3.2中新添加的配置項(xiàng)。指定format格式字符串的風(fēng)格睹逃,可取值為'%'盗扇、'{'和'$',默認(rèn)為'%'
handlers | Python 3.3中新添加的配置項(xiàng)沉填。該選項(xiàng)如果被指定疗隶,它應(yīng)該是一個(gè)創(chuàng)建了多個(gè)Handler的可迭代對(duì)象,這些handler將會(huì)被添加到root logger翼闹。需要說(shuō)明的是:filename斑鼻、stream和handlers這三個(gè)配置項(xiàng)只能有一個(gè)存在,不能同時(shí)出現(xiàn)2個(gè)或3個(gè)猎荠,否則會(huì)引發(fā)ValueError異常坚弱。
  1. logging模塊定義的格式字符串字段
    我們來(lái)列舉一下logging模塊中定義好的可以用于format格式字符串中字段有哪些:
字段/屬性名稱 | 使用格式 | 描述
| - | -
asctime | %(asctime)s | 日志事件發(fā)生的時(shí)間--人類可讀時(shí)間蜀备,如:2003-07-08 16:49:45,896
created | %(created)f | 日志事件發(fā)生的時(shí)間--時(shí)間戳,就是當(dāng)時(shí)調(diào)用time.time()函數(shù)返回的值
relativeCreated | %(relativeCreated)d | 日志事件發(fā)生的時(shí)間相對(duì)于logging模塊加載時(shí)間的相對(duì)毫秒數(shù)(目前還不知道干嘛用的)
msecs | %(msecs)d | 日志事件發(fā)生事件的毫秒部分
levelname | %(levelname)s | 該日志記錄的文字形式的日志級(jí)別('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
levelno | %(levelno)s | 該日志記錄的數(shù)字形式的日志級(jí)別(10, 20, 30, 40, 50)
name | %(name)s | 所使用的日志器名稱荒叶,默認(rèn)是'root'碾阁,因?yàn)槟J(rèn)使用的是 rootLogger
message | %(message)s | 日志記錄的文本內(nèi)容,通過(guò) msg % args計(jì)算得到的
pathname | %(pathname)s | 調(diào)用日志記錄函數(shù)的源碼文件的全路徑
filename | %(filename)s | pathname的文件名部分些楣,包含文件后綴
module | %(module)s | filename的名稱部分脂凶,不包含后綴
lineno | %(lineno)d | 調(diào)用日志記錄函數(shù)的源代碼所在的行號(hào)
funcName | %(funcName)s | 調(diào)用日志記錄函數(shù)的函數(shù)名
process | %(process)d | 進(jìn)程ID
processName | %(processName)s | 進(jìn)程名稱,Python 3.1新增
thread | %(thread)d | 線程ID
threadName | %(thread)s | 線程名稱

5.經(jīng)過(guò)配置的日志輸出
先簡(jiǎn)單配置下日志器的日志級(jí)別

logging.basicConfig(level=logging.DEBUG)

logging.debug("This is a debug log.")
logging.info("This is a info log.")
logging.warning("This is a warning log.")
logging.error("This is a error log.")
logging.critical("This is a critical log.")

輸出結(jié)果:

DEBUG:root:This is a debug log.
INFO:root:This is a info log.
WARNING:root:This is a warning log.
ERROR:root:This is a error log.
CRITICAL:root:This is a critical log.

所有等級(jí)的日志信息都被輸出了戈毒,說(shuō)明配置生效了艰猬。

在配置日志器日志級(jí)別的基礎(chǔ)上,在配置下日志輸出目標(biāo)文件和日志格式

LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
logging.basicConfig(filename='my.log', level=logging.DEBUG, format=LOG_FORMAT)

logging.debug("This is a debug log.")
logging.info("This is a info log.")
logging.warning("This is a warning log.")
logging.error("This is a error log.")
logging.critical("This is a critical log.")

此時(shí)會(huì)發(fā)現(xiàn)控制臺(tái)中已經(jīng)沒(méi)有輸出日志內(nèi)容了埋市,但是在python代碼文件的相同目錄下會(huì)生成一個(gè)名為'my.log'的日志文件冠桃,該文件中的內(nèi)容為:

2017-05-08 14:29:53,783 - DEBUG - This is a debug log.
2017-05-08 14:29:53,784 - INFO - This is a info log.
2017-05-08 14:29:53,784 - WARNING - This is a warning log.
2017-05-08 14:29:53,784 - ERROR - This is a error log.
2017-05-08 14:29:53,784 - CRITICAL - This is a critical log.

在上面的基礎(chǔ)上,我們?cè)賮?lái)設(shè)置下日期/時(shí)間格式

LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"

logging.basicConfig(filename='my.log', level=logging.DEBUG, format=LOG_FORMAT, datefmt=DATE_FORMAT)
logging.debug("This is a debug log.")
logging.info("This is a info log.")
logging.warning("This is a warning log.")
logging.error("This is a error log.")
logging.critical("This is a critical log.")

此時(shí)會(huì)在my.log日志文件中看到如下輸出內(nèi)容:

05/08/2017 14:29:04 PM - DEBUG - This is a debug log.
05/08/2017 14:29:04 PM - INFO - This is a info log.
05/08/2017 14:29:04 PM - WARNING - This is a warning log.
05/08/2017 14:29:04 PM - ERROR - This is a error log.
05/08/2017 14:29:04 PM - CRITICAL - This is a critical log.

掌握了上面的內(nèi)容之后道宅,已經(jīng)能夠滿足我們平時(shí)開(kāi)發(fā)中需要的日志記錄功能食听。

封裝一下

import os
import logging
# debug -> info -> warn -> error -> critical
def getLogger(name, saveDir="./log/", maxBytes=20 * 1024 * 1024, backupCount=20, hasInit=False):
    if not os.path.exists(saveDir):
        os.system("mkdir -p %s" % saveDir)
    
    logger = logging.getLogger(name)
    if not hasInit:
        logger.setLevel(logging.DEBUG) 

        # 處理文件輸出,輸出所有級(jí)別
        logFile = "%s/%s.log" % (saveDir,  name)
        formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] [%(funcName)s:%(lineno)s] %(message)s")
        fileHandler = RotatingFileHandler(logFile, maxBytes=maxBytes, backupCount=backupCount)
        fileHandler.setLevel(logging.DEBUG)
        fileHandler.setFormatter(formatter)
        logger.addHandler(fileHandler)
        
        # 標(biāo)準(zhǔn)輸出(屏幕)
        stdoutFormatter = logging.Formatter("\033[1;32;40m[%(asctime)s] [%(levelname)s] [%(funcName)s:%(lineno)s] %(message)s\033[0m")
        stdoutHandler = logging.StreamHandler(sys.stdout)
        stdoutHandler.setLevel(logging.INFO)
        stdoutHandler.setFormatter(stdoutFormatter)
        stdoutHandler.addFilter(InfoFilter(logging.INFO))
        logger.addHandler(stdoutHandler)
        
        # 錯(cuò)誤輸出(屏幕)
        stderrFormatter = logging.Formatter("\033[1;31;40m[%(asctime)s] [%(levelname)s] [%(funcName)s:%(lineno)s] %(message)s\033[0m")
        stderrHandler = logging.StreamHandler(sys.stderr)
        stderrHandler.setLevel(logging.WARNING)
        stderrHandler.setFormatter(stderrFormatter)
        logger.addHandler(stderrHandler)
        
        # propagate 屬性為 True(默認(rèn)值)污茵,則它的記錄也會(huì)傳到父 logger樱报。因此,logger 在記錄到文件的同時(shí)泞当,也會(huì)在 stdout 輸出日志迹蛤。
        logger.propagate = False # duplicate log
    return logger

# 調(diào)用
getLogger(test)

調(diào)用結(jié)果:在當(dāng)前路徑的log下生成文件名為test.log的文件,里面會(huì)有各類日志襟士。

logging.Formatter 的常用格式字符串

格式字符串 作用
%(name)s 日志記錄器的名稱(記錄通道)
%(levelno)s 日志記錄級(jí)別的數(shù)字
DEBUG=10盗飒、INFO=20、WARNING=30陋桂、ERROR=40逆趣、CRITICAL=50
%(levelname)s 日志記錄級(jí)別的文本
“DEBUG”、“INFO”嗜历、“WARNING”宣渗、“ERROR”、“CRITICAL”
%(pathname)s 日志調(diào)用的源文件的完整路徑名
%(filename)s 日志調(diào)用的源文件的文件名部分
%(module)s 日志調(diào)用的源文件的文件名的名稱部分
%(lineno)d 日志調(diào)用的源行號(hào)
%(funcName)s 日志調(diào)用的函數(shù)名
%(created)f 打印日志的時(shí)間 time.time() 的返回值
%(asctime)s 打印日志的時(shí)間 datetime.datetime.now() 的返回值
%(msecs)d 打印日志的毫秒部分
%(relativeCreated)d 打印日志的時(shí)間梨州,毫秒為單位 是相對(duì)于加載 logging 模塊的時(shí)間(通常在應(yīng)用程序啟動(dòng)時(shí))
%(thread)d 線程ID
%(threadName)s 線程名痕囱,一般是主線程 MainThread
%(process)d 進(jìn)程ID
%(message)s 日志信息
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市暴匠,隨后出現(xiàn)的幾起案子咐蝇,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件有序,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡岛请,警方通過(guò)查閱死者的電腦和手機(jī)旭寿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)崇败,“玉大人盅称,你說(shuō)我怎么就攤上這事『笫遥” “怎么了缩膝?”我有些...
    開(kāi)封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)岸霹。 經(jīng)常有香客問(wèn)我疾层,道長(zhǎng),這世上最難降的妖魔是什么贡避? 我笑而不...
    開(kāi)封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任痛黎,我火速辦了婚禮,結(jié)果婚禮上刮吧,老公的妹妹穿的比我還像新娘湖饱。我一直安慰自己,他們只是感情好杀捻,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布井厌。 她就那樣靜靜地躺著,像睡著了一般致讥。 火紅的嫁衣襯著肌膚如雪仅仆。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天拄踪,我揣著相機(jī)與錄音蝇恶,去河邊找鬼。 笑死惶桐,一個(gè)胖子當(dāng)著我的面吹牛撮弧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播姚糊,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼贿衍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了救恨?” 一聲冷哼從身側(cè)響起贸辈,我...
    開(kāi)封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肠槽,沒(méi)想到半個(gè)月后擎淤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體奢啥,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年嘴拢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了桩盲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡席吴,死狀恐怖赌结,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情孝冒,我是刑警寧澤柬姚,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站庄涡,受9級(jí)特大地震影響量承,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜啼染,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一宴合、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迹鹅,春花似錦卦洽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至弟蚀,卻和暖如春蚤霞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背义钉。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工昧绣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捶闸。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓夜畴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親删壮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贪绘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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

  • 本文章是我大概三年前,在上家單位使用 Python 工作時(shí)結(jié)合官方文檔做的整理⊙氲現(xiàn)在 Python 官方文檔聽(tīng)說(shuō)已...
    好吃的野菜閱讀 216,517評(píng)論 14 232
  • 一税灌、介紹 通過(guò)log分析可獲取程序的運(yùn)行情況,也可快速定位問(wèn)題; 調(diào)試階段:一般需要所有的運(yùn)行日志來(lái)分析菱涤;發(fā)布階段...
    rr1990閱讀 708評(píng)論 0 1
  • logging模塊當(dāng)中苞也,記錄到log的信息等級(jí)劃分:從低到高 調(diào)試(debug)、信息(info)粘秆、警告(warn...
    卅清閱讀 1,122評(píng)論 0 0
  • 一.logging模塊簡(jiǎn)介 logging模塊是Python內(nèi)置的標(biāo)準(zhǔn)模塊墩朦,主要用于輸出運(yùn)行日志,可以設(shè)置輸出日志...
    只是甲閱讀 115評(píng)論 0 0
  • logging模塊提供了兩種記錄日志的方式:一種是使用logging提供的模塊級(jí)別的函數(shù)翻擒;另一種是使用loggin...
    vvvillian閱讀 320評(píng)論 0 0