2017-10-07 21 views
1

我正在使用兩個日誌記錄處理程序。一個用於DEBUG級別以上的文件,另一個用於WARNING及以上的控制檯。 我使用了很多模塊,其中一些是外部的(使用pip安裝)。當有logging.info()呼叫(而不是logger.info()),該沉船爲控制檯記錄器設置:使用logging.info而不是logger.info wrecks StreamHandler

import logging 
import logging.handlers 
import sys, os 
from demo_module import something, something_else 

logger = logging.getLogger("demo") 
logger.setLevel(logging.DEBUG) 
main_handler = logging.FileHandler('demo.log') 
formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)-8s %(filename)s:%(lineno)d %(message)s') 
main_handler.setFormatter(formatter) 
logger.addHandler(main_handler) 

# log serious issues to console 
console_handler = logging.StreamHandler(stream=sys.stderr) 
console_handler.setLevel(logging.WARNING) 
console_handler.setFormatter(formatter) 
logger.addHandler(console_handler) 
logger.debug('this is a debug') 
logger.info('this is an info') 
logger.warning('this is a warning') 
logger.error('this is an error') 
logger.critical('reactor has melted down') 
something() 
logger.info('after something') 
something_else() 
logger.info('after something else') 

其中demo_module.py是:

import logging 
logger = logging.getLogger('demo') 

def something(): 
    logger.info('something needs to be done') 
    a = 1+1 
    logger.info('something has been done') 
    logger.error('some banale error') 

def something_else(): 
    logger.info('calling logger.info') 
    # OOPS, calling logging instead of logger here 
    logging.info("module may use logging directly instead of logger") 
    logger.info('logger.info called') 

正如你可以看到,裏面demo_module.something_else()有一個呼叫logging.info而不是logger.info

輸出到控制檯看起來是這樣的:

% python logger.py 
2017-10-07 17:45:08,077 demo WARNING logger2.py:21 this is a warning 
2017-10-07 17:45:08,077 demo ERROR logger2.py:22 this is an error 
2017-10-07 17:45:08,077 demo CRITICAL logger2.py:23 reactor has melted down 
2017-10-07 17:45:08,078 demo ERROR demo_module.py:8 some banale error 
INFO:demo:logger.info called 
INFO:demo:after something else 

正如你所看到的,最後兩行失去了我最初的設置控制檯處理程序的所有設置,如水平,而且該格式。 如果只是我的代碼,我可以找到這個違反logging.info()聲明並替換它,但一些代碼不是我的,但第三方,因此這是我無法控制的。 任何想法如何使這些設置堅持?

回答

1

默認情況下,模塊級別日誌記錄功能將調用logging.basicConfig()來嘗試配置根日誌記錄器。 Docs

...模塊級便利功能,這代表對根記錄,調用basicConfig(),以確保至少一個處理程序是可用的。

logging.basicConfigdocs狀態:

這個函數做什麼,如果根記錄器已經爲它配置了處理程序。

所以解決的辦法就是任何模塊級別的日誌功能得到所謂的之前對根記錄配置的處理器,同時還指示你的記錄器沒有將消息傳播了記錄器的層次結構,以避免重複輸出。

import logging 
import logging.handlers 
import sys, os 
from demo import something, something_else 

formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)-8s %(filename)s:%(lineno)d %(message)s') 

# Configure the root logger. 
root_logger = logging.getLogger() 
root_logger.setLevel(logging.DEBUG) 
# Configure file handler. 
root_main_handler = logging.FileHandler('demo.log') 
root_main_handler.setFormatter(formatter) 
root_logger.addHandler(root_main_handler) 
# Configure console handler. 
root_console_handler = logging.StreamHandler(stream=sys.stderr) 
root_console_handler.setLevel(logging.WARNING) 
root_console_handler.setFormatter(formatter) 
root_logger.addHandler(root_console_handler) 

logger = logging.getLogger("demo") 
logger.setLevel(logging.DEBUG) 
main_handler = logging.FileHandler('demo.log') 
main_handler.setFormatter(formatter) 
logger.addHandler(main_handler) 

# log serious issues to console 
console_handler = logging.StreamHandler(stream=sys.stderr) 
console_handler.setLevel(logging.WARNING) 
console_handler.setFormatter(formatter) 
logger.addHandler(console_handler) 
# Don't propagate messages up to the root logger. 
logger.propagate = False 
logger.debug('this is a debug') 
logger.info('this is an info') 
logger.warning('this is a warning') 
logger.error('this is an error') 
logger.critical('reactor has melted down') 
something() 
logger.info('after something') 
something_else() 
logger.info('after something else') 

控制檯輸出:

2017-10-07 18:46:50,644 demo WARNING run.py:35 this is a warning 
2017-10-07 18:46:50,644 demo ERROR run.py:36 this is an error 
2017-10-07 18:46:50,644 demo CRITICAL run.py:37 reactor has melted down 
2017-10-07 18:46:50,645 demo ERROR demo.py:8 some banale error 

文件輸出:

2017-10-07 18:46:50,644 demo DEBUG run.py:33 this is a debug 
2017-10-07 18:46:50,644 demo INFO  run.py:34 this is an info 
2017-10-07 18:46:50,644 demo WARNING run.py:35 this is a warning 
2017-10-07 18:46:50,644 demo ERROR run.py:36 this is an error 
2017-10-07 18:46:50,644 demo CRITICAL run.py:37 reactor has melted down 
2017-10-07 18:46:50,645 demo INFO  demo.py:5 something needs to be done 
2017-10-07 18:46:50,645 demo INFO  demo.py:7 something has been done 
2017-10-07 18:46:50,645 demo ERROR demo.py:8 some banale error 
2017-10-07 18:46:50,645 demo INFO  run.py:39 after something 
2017-10-07 18:46:50,645 demo INFO  demo.py:11 calling logger.info 
2017-10-07 18:46:50,645 root INFO  demo.py:13 module may use logging directly instead of logger 
2017-10-07 18:46:50,645 demo INFO  demo.py:14 logger.info called 
2017-10-07 18:46:50,645 demo INFO  run.py:41 after something else