30天拿下Python之logging模塊

概述

在上一節(jié),我們介紹了Python的collections模塊,包括:collections模塊中一些常用的函數(shù)和類。在這一節(jié)靴迫,我們將介紹Python的logging模塊。logging模塊是一個(gè)用于記錄和調(diào)試的標(biāo)準(zhǔn)庫(kù)楼誓,它提供了一種靈活的方式來記錄不同級(jí)別的消息玉锌,比如:調(diào)試信息、錯(cuò)誤信息疟羹、警告信息等主守。這個(gè)模塊非常有用禀倔,因?yàn)樗梢詭椭_發(fā)者理解應(yīng)用程序在運(yùn)行時(shí)到底發(fā)生了什么。當(dāng)程序出現(xiàn)錯(cuò)誤或異常時(shí)参淫,通過合理的日志記錄救湖,我們可以迅速定位問題,了解問題的來龍去脈涎才。

logging的基本使用

在Python中捎谨,logging模塊的使用比較簡(jiǎn)單。導(dǎo)入logging模塊后憔维,通過調(diào)用basicConfig方法可以進(jìn)行基本的配置。比如:可以設(shè)置日志級(jí)別畏邢、日志輸出位置业扒、日志格式等。

import logging
logging.basicConfig(level = logging.INFO,
                    format = '%(asctime)s - %(levelname)s - %(message)s',
                    filename = 'app.log',
                    filemode = 'w')

進(jìn)行上述的基本配置后舒萎,我們就可以創(chuàng)建logger對(duì)象程储,并調(diào)用其各種方法來記錄日志信息了。

logger = logging.getLogger('my_logger')
logger.debug('Debug message')
logger.info('Info message')
logger.warning('Warning message')
logger.error('Error message')
logger.critical('Critical message')

執(zhí)行上述的示例代碼后臂寝,會(huì)在當(dāng)前目錄下生成app.log文件章鲤,其內(nèi)容如下。

2023-09-24 19:44:43,086 - INFO - Info message
2023-09-24 19:44:43,086 - WARNING - Warning message
2023-09-24 19:44:43,086 - ERROR - Error message
2023-09-24 19:44:43,086 - CRITICAL - Critical message

可以看到咆贬,logger.debug函數(shù)寫入的調(diào)試信息沒有出現(xiàn)在文件中败徊。這是因?yàn)椋覀冎付巳罩炯?jí)別為logging.INFO掏缎,比該日志級(jí)別低的信息會(huì)被過濾掉皱蹦,不會(huì)寫入日志文件中。

logging的選項(xiàng)設(shè)置

logging模塊提供了很多選項(xiàng)來配置日志記錄的行為眷蜈,以下是一些常見的選項(xiàng)沪哺。
日志記錄器名稱:每個(gè)記錄器都有一個(gè)名稱,可以通過名稱來獲取和配置特定的記錄器酌儒。
日志級(jí)別:一共有五個(gè)級(jí)別的日志記錄辜妓,從低到高依次為:DEBUG、INFO忌怎、WARNING籍滴、ERROR、
CRITICAL榴啸。我們可以設(shè)置日志記錄器的級(jí)別异逐,這樣低于該級(jí)別的所有消息都不會(huì)被記錄。比如:如果級(jí)別設(shè)置為WARNING插掂,那么DEBUG和INFO級(jí)別的消息將不會(huì)被記錄灰瞻。
日志格式:可以通過設(shè)置日志記錄器的格式字符串來改變?nèi)罩鞠⒌娘@示方式腥例。比如:可以包含時(shí)間戳、日志級(jí)別酝润、消息燎竖、線程名等。
日志輸出地:日志消息可以輸出到多種地方要销,比如:控制臺(tái)构回、文件等∈韪溃可以使用多種Handler來實(shí)現(xiàn)纤掸,比如:輸出到控制臺(tái)使用StreamHandler、輸出到文件使用FileHandler等浑塞。
日志旋轉(zhuǎn):如果日志文件可能會(huì)變得很大借跪,我們需要在滿足某個(gè)條件(比如:日志文件達(dá)到一定大小)時(shí)創(chuàng)建一個(gè)新的日志文件酌壕,這可以通過使用RotatingFileHandler或TimedRotatingFileHandler等處理程序來實(shí)現(xiàn)掏愁。
日志過濾:可以通過使用過濾器來進(jìn)一步定制哪些消息應(yīng)該被記錄。比如:我們可以設(shè)置一個(gè)過濾器卵牍,只有包含特定關(guān)鍵字的消息才會(huì)被記錄果港。
在下面的示例代碼中,我們創(chuàng)建了一個(gè)名為'my_logger'的日志記錄器糊昙,并設(shè)置了其級(jí)別為DEBUG辛掠。然后,我們創(chuàng)建了一個(gè)寫入日志文件的處理器和一個(gè)輸出到控制臺(tái)的處理器释牺,并設(shè)置了他們的級(jí)別公浪。我們還定義了日志消息的格式,并將其應(yīng)用到了兩個(gè)處理器上船侧。最后欠气,我們用這個(gè)記錄器記錄了一條警告信息。

import logging

# 創(chuàng)建一個(gè)logger
logger = logging.getLogger('my_logger')
# 設(shè)置日志級(jí)別
logger.setLevel(logging.DEBUG)
  
# 創(chuàng)建一個(gè)Handler镜撩,用于寫入日志文件
fileHandler = logging.FileHandler('app.log')
# 設(shè)置日志級(jí)別
fileHandler.setLevel(logging.DEBUG)

# 創(chuàng)建一個(gè)Handler预柒,用于輸出到控制臺(tái)
consoleHandler = logging.StreamHandler()
# 設(shè)置日志級(jí)別
consoleHandler.setLevel(logging.INFO)

# 定義Handler的輸出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fileHandler.setFormatter(formatter)
consoleHandler.setFormatter(formatter)

# 給logger添加Handler
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)

# 記錄一條日志
# 輸出:2023-09-24 20:06:26,828 - my_logger - WARNING - a warning info
logger.warn('a warning info')

日志旋轉(zhuǎn)

在logging模塊中,可以使用RotatingFileHandler和TimedRotatingFileHandler來實(shí)現(xiàn)日志旋轉(zhuǎn)袁梗。
RotatingFileHandler根據(jù)日志文件的大小來旋轉(zhuǎn)日志文件宜鸯。可以通過設(shè)置maxBytes參數(shù)來指定每個(gè)日志文件的大小遮怜,同時(shí)通過backupCount參數(shù)來指定保留的備份文件數(shù)量淋袖。當(dāng)日志文件達(dá)到設(shè)定的最大大小時(shí),原日志文件將被重命名并備份锯梁,同時(shí)開始寫入新的日志文件即碗。
TimedRotatingFileHandler則根據(jù)時(shí)間間隔來旋轉(zhuǎn)日志文件焰情。可以通過設(shè)置interval參數(shù)來指定時(shí)間間隔剥懒,同時(shí)通過backupCount參數(shù)來指定保留的備份文件數(shù)量内舟。當(dāng)達(dá)到設(shè)定的時(shí)間間隔時(shí),原日志文件將被重命名并備份初橘,同時(shí)開始寫入新的日志文件验游。

import logging
import logging.handlers
  
# 創(chuàng)建一個(gè)Logger對(duì)象
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# 創(chuàng)建一個(gè)RotatingFileHandler對(duì)象
maxSize = 1 << 20
handler = logging.handlers.RotatingFileHandler('app.log', maxBytes = maxSize, backupCount = 5)
  
# 設(shè)置日志級(jí)別和格式
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

# 記錄日志消息
logger.info('Info message')

在上面的示例代碼中,我們創(chuàng)建了一個(gè)RotatingFileHandler對(duì)象保檐,并指定了日志文件的最大大小為1MB字節(jié)耕蝉,同時(shí)保留5個(gè)備份文件。當(dāng)日志文件達(dá)到設(shè)定的最大大小時(shí)夜只,原日志文件將被重命名并備份垒在,同時(shí)開始寫入新的日志文件。

logging.Filter類

logging.Filter類用于過濾日志消息盐肃。它有一個(gè)名為filter的函數(shù),用于確定是否應(yīng)該記錄或傳遞日志消息权悟。我們可以創(chuàng)建一個(gè)Filter類的派生類砸王,并覆蓋其filter函數(shù)。該函數(shù)接受一個(gè)日志記錄對(duì)象作為參數(shù)峦阁,并返回一個(gè)布爾值谦铃,用于表示是否應(yīng)該記錄或傳遞該日志消息。如果該函數(shù)返回True榔昔,則日志消息將被記錄或傳遞驹闰,否則將被忽略。

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

my_logger = logging.getLogger('my_logger')
my_logger.setLevel(logging.DEBUG)

# 創(chuàng)建一個(gè)名為my_handler的處理器撒会,并將其添加到my_logger中
my_handler = logging.StreamHandler()
my_handler.setLevel(logging.DEBUG)
my_handler.setFormatter(logging.Formatter(LOG_FORMAT))
my_logger.addHandler(my_handler)
  
# 創(chuàng)建一個(gè)名為filter的過濾器嘹朗,并將其添加到my_handler中
class CustomFilter(logging.Filter):
    def filter(self, record):
        return 'Hope' in record.msg
filter = CustomFilter()
my_handler.addFilter(filter)
  
# 記錄一些消息
my_logger.debug('Hello Hope')
my_logger.info('Hello World')
my_logger.warning('Hope web site')
my_logger.error('GitHub web site')

在上面的示例代碼中,我們首先使用basicConfig方法定義了一個(gè)基本的日志配置诵肛。然后屹培,創(chuàng)建了一個(gè)名為my_logger的記錄器,并將其級(jí)別設(shè)置為DEBUG怔檩。接下來褪秀,我們創(chuàng)建了一個(gè)名為my_handler的處理器,并將其添加到my_logger中薛训。我們還創(chuàng)建了一個(gè)名為filter的過濾器媒吗,并將其添加到my_handler中,以過濾掉日志信息中不包含"Hope"字符串的日志乙埃。最后闸英,我們使用my_logger記錄了幾條不同級(jí)別的日志消息锯岖。執(zhí)行上面的代碼后,只有“Hello Hope”和“Hope web site”這兩條日志信息會(huì)被保存和輸出自阱。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嚎莉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子沛豌,更是在濱河造成了極大的恐慌趋箩,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件加派,死亡現(xiàn)場(chǎng)離奇詭異叫确,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)芍锦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門竹勉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人娄琉,你說我怎么就攤上這事次乓。” “怎么了孽水?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵票腰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我女气,道長(zhǎng)杏慰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任炼鞠,我火速辦了婚禮缘滥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谒主。我一直安慰自己朝扼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布霎肯。 她就那樣靜靜地躺著吟税,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姿现。 梳的紋絲不亂的頭發(fā)上肠仪,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天,我揣著相機(jī)與錄音备典,去河邊找鬼异旧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛提佣,可吹牛的內(nèi)容都是我干的吮蛹。 我是一名探鬼主播荤崇,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼潮针!你這毒婦竟也來了术荤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤每篷,失蹤者是張志新(化名)和其女友劉穎瓣戚,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焦读,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡子库,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矗晃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仑嗅。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖张症,靈堂內(nèi)的尸體忽然破棺而出仓技,到底是詐尸還是另有隱情,我是刑警寧澤俗他,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布脖捻,位于F島的核電站,受9級(jí)特大地震影響拯辙,放射性物質(zhì)發(fā)生泄漏郭变。R本人自食惡果不足惜颜价,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一涯保、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧周伦,春花似錦夕春、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至寨腔,卻和暖如春速侈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背迫卢。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工倚搬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乾蛤。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓每界,卻偏偏與公主長(zhǎng)得像捅僵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子眨层,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

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