2015-06-25 68 views
0

我想加強我的Python腳本中的日誌記錄,我很感激能不能與我分享最佳實踐。現在我創造了這個小腳本(我應該說我運行Python 3.4)多流處理程序

import logging 
import io 
import sys 

def Streamhandler(stream, level, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"): 
    ch = logging.StreamHandler(stream) 
    ch.setLevel(level) 
    formatter = logging.Formatter(format) 
    ch.setFormatter(formatter) 
    return ch 


# get the root logger 
logger = logging.getLogger() 

stream = io.StringIO() 
logger.addHandler(Streamhandler(stream, logging.WARN)) 

stream_error = io.StringIO() 
logger.addHandler(Streamhandler(stream_error, logging.ERROR)) 

logger.addHandler(Streamhandler(stream=sys.stdout, level=logging.DEBUG)) 

print(logger) 
for h in logger.handlers: 
    print(h) 
    print(h.level) 

# 'application' code # goes to the root logger! 
logging.debug('debug message') 
logging.info('info message') 
logging.warning('warn message') 
logging.error('error message') 
logging.critical('critical message') 

print(stream.getvalue()) 
print(stream_error.getvalue()) 

我有三個處理,其中2寫入到io.StringIO(這似乎工作)。我需要這個來簡化測試,但也需要通過HTTP電子郵件服務發送日誌。然後有一個控制檯的Streamhandler。但是,儘管將該級別明確設置得足夠低,但在控制檯上會忽略logging.debug和logging.info消息?

回答

1

首先,你沒有設置級別的記錄器本身:

logger.setLevel(logging.DEBUG) 

而且,你可以定義一個logger,但在logging上進行呼叫 - 這將調用根記錄器。不是因爲您沒有爲您的記錄器指定名稱,所以會對您的案例產生任何影響,因此logging.getLogger()會返回根記錄器。

關於「最佳實踐」,它的確取決於腳本的複雜程度,當然也取決於您的日誌記錄需求。

對於簡單用例(單個已知環境,無併發執行,簡單登錄到文件或stderr等)的自包含簡單腳本,簡單地調用logging.basicConfig()並直接調用logging.whatever()通常就足夠了。

對於任何更復雜,最好使用不同的配置文件 - 無論是在ini格式或Python的字典(使用logging.dictConfig),拆你的腳本爲不同的模塊(S)或包(s)每個定義它自己的命名記錄器(與logger = logging.getLogger(__name__)),並且只保留腳本本身作爲代碼的「runner」,即:配置日誌記錄,導入模塊,解析命令行參數並調用主函數 - 最好在try/except塊中,以正確記錄任何崩潰前未處理的異常。

+0

我想我最終解釋了logger = logging.getLogger(「MyLogger」)到模塊和包的更深層次。我對模塊定義自己的記錄器持懷疑態度...... – tschm

+1

@tschm模塊需要一個記錄器來記錄任何東西,它需要的只是一個「導入記錄; logger = logging.getLogger(__ name __)'行開頭(** no ** config在這裏完成)。這是進行日誌記錄的預期方式:記錄器根據記錄器名稱形成一個層次結構('foo.bar'是'foo'的子元素,它是'root'的子元素),如果沒有明確配置,記錄器會傳播給它parent - 這樣做可以確保我們正確構建了這個層次結構,然後如果需要,您可以完全控制每個包/模塊/子模塊的日誌配置,或者只需配置根日誌記錄器。 –

+0

它開始有意義:-)。雖然我的主要功能是調用3個不同的包(這可能表明我應該做一些重構)。在這個階段,我決定使用def f(x,logger = None):並且在使用日誌記錄的函數和類中包含logger = logger或logging.getLogger(__ name__)。所以我可以解析我的主要功能的記錄器給我的客戶,但我不必。使用這個(骯髒的)技巧,我只需要配置一個記錄器來統一它們。 – tschm

1

一個loggerthreshold level也一樣,你需要將其設置爲DEBUG第一:

logger.setLevel(logging.DEBUG)