自定義logging函式中重複列印問題

2022-04-03 03:22:35 字數 3820 閱讀 5334

最近碰到了這個問題,很頭疼。幸虧找到了這篇文章:

其實還有乙個解決方法,就是直接在模組裡面生成乙個logger物件,這樣載入模組時就只載入一次,不會出現重複呼叫函式,載入handler的現象。

用python的logging模組記錄日誌時,遇到了重覆記錄日誌的問題,第一條記錄寫一次,第二條記錄寫兩次,第三條記錄寫三次。。。很頭疼,這樣記日誌可不行。網上搜尋到了原因與解決方案:

原因:沒有移除handler

解決:在日誌記錄完之後removehandler

修改前示例**:

import logging

def log(message):

logger = logging.getlogger('testlog')

streamhandler = logging.streamhandler()

streamhandler.setlevel(logging.error)

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

streamhandler.setformatter(formatter)

logger.addhandler(streamhandler)

logger.error(message)

if __name__ == '__main__':

log('hi')

log('hi too')

log('hi three')

修改前輸出結果:

2016-07-08 09:17:29,740 - error - testlog - hi 

2016-07-08 09:17:29,740 - error - testlog - hi too 

2016-07-08 09:17:29,740 - error - testlog - hi too 

2016-07-08 09:17:29,740 - error - testlog - hi three 

2016-07-08 09:17:29,740 - error - testlog - hi three 

2016-07-08 09:17:29,740 - error - testlog - hi three

修改後示例**:

import logging

def log(message):

logger = logging.getlogger('testlog')

streamhandler = logging.streamhandler()

streamhandler.setlevel(logging.error)

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

streamhandler.setformatter(formatter)

logger.addhandler(streamhandler)

logger.error(message)

# 新增下面一句,在記錄日誌之後移除控制代碼

logger.removehandler(streamhandler)

if __name__ == '__main__':

log('hi')

log('hi too')

log('hi three')

修改後輸出結果:

2016-07-08 09:32:28,206 - error - testlog - hi 

2016-07-08 09:32:28,206 - error - testlog - hi too 

2016-07-08 09:32:28,206 - error - testlog - hi three

google之後,大概搞明白了,就是你第二次呼叫log的時候,根據getlogger(name)裡的name獲取同乙個logger,而這個logger裡已經有了第一次你新增的handler,第二次呼叫又新增了乙個handler,所以,這個logger裡有了兩個同樣的handler,以此類推,呼叫幾次就會有幾個handler。。

所以這裡有以下幾個解決辦法:

每次建立不同name的logger,每次都是新logger,不會有新增多個handler的問題。(ps:這個辦法太笨,不過我之前就是這麼幹的。。)

像上面一樣每次記錄完日誌之後,呼叫removehandler()把這個logger裡的handler移除掉。

在log方法裡做判斷,如果這個logger已有handler,則不再新增handler。

與方法2一樣,不過把用pop把logger的handler列表中的handler移除。

下面是方法3與方法4的**示例:

方法3:

import logging

def log(message):

logger = logging.getlogger('testlog')

# 這裡進行判斷,如果logger.handlers列表為空,則新增,否則,直接去寫日誌

if not logger.handlers:

streamhandler = logging.streamhandler()

streamhandler.setlevel(logging.error)

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

streamhandler.setformatter(formatter)

logger.addhandler(streamhandler)

logger.error(message)

if __name__ == '__main__':

log('hi')

log('hi too')

log('hi three')

方法4:

import logging

def log(message):

logger = logging.getlogger('testlog')

streamhandler = logging.streamhandler()

streamhandler.setlevel(logging.error)

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

streamhandler.setformatter(formatter)

logger.addhandler(streamhandler)

logger.error(message)

# 用pop方法把logger.handlers列表中的handler移除,注意如果你add了多個handler,這裡需多次pop,或者可以直接為handlers列表賦空值

logger.handlers.pop()

# logger.handler =

if __name__ == '__main__':

log('hi')

log('hi too')

log('hi three')

自定義函式 Excel之自定義函式

在excel中,當系統函式不能滿足我們的需求時候,我們可以使用vba自定義函式,如抓取網頁資料,翻譯詞彙,手機號歸屬地查詢等。下面將介紹2個自定義函式,idymd函式 身份證年月日性別 通過身份證號,返回性別,出生年月日。語法 idymd id 引數 id,身份證號,預設身份證長度18位。vba 如...

awk中自定義函式

awk中自定義函式 定義和呼叫使用者自己的函式是幾乎每個高階語言都具有的功能,awk也不例外,但原始的awk並不提供函式功能,只有在nawk或較新的awk版本中才可以增加函式。函式的使用包含兩部分 函式的定義與函式呼叫。其中函式定義又包括要執行的 函式本身 和從主程式 傳遞到該函式的臨時呼叫。awk...

sql server中自定義函式

create function getzhye nm varchar 300 returns float as begin declare membername float set membername 0 select membername 欄位1 from 表a where 欄位2 nm if ...