用Python(通過日誌記錄模塊)臨時更改日誌消息格式的最簡單方法是什麼?如何在Python中臨時更改記錄消息的格式?
目標是擁有一些標準的消息格式,同時能夠臨時添加有關正在讀取的某個文件(如其名稱)的信息;當文件不再被讀取時,消息格式應該恢復爲默認值。產生這些消息的程序是而不是意識到正在讀取什麼文件,所以如果它的消息自動包含相關的文件名(如果錯誤消息是:「ERROR ,同時讀取文件 ***: ...「而不是」錯誤:...「)。
用Python(通過日誌記錄模塊)臨時更改日誌消息格式的最簡單方法是什麼?如何在Python中臨時更改記錄消息的格式?
目標是擁有一些標準的消息格式,同時能夠臨時添加有關正在讀取的某個文件(如其名稱)的信息;當文件不再被讀取時,消息格式應該恢復爲默認值。產生這些消息的程序是而不是意識到正在讀取什麼文件,所以如果它的消息自動包含相關的文件名(如果錯誤消息是:「ERROR ,同時讀取文件 ***: ...「而不是」錯誤:...「)。
這是一個簡單的解決方案,可以從Vinay Sajip自己的HOWTO推導出來;它基本上更新日誌記錄格式化與setFormatter()
:
import logging
logger = logging.getLogger() # Logger
logger_handler = logging.StreamHandler() # Handler for the logger
logger.addHandler(logger_handler)
# First, generic formatter:
logger_handler.setFormatter(logging.Formatter('%(message)s'))
logger.error('error message') # Test
# New formatter for the handler:
logger_handler.setFormatter(logging.Formatter('PROCESSING FILE xxx - %(message)s'))
logger.error('error message') # Test
此正確地產生:
error message
PROCESSING FILE xxx - error message
(其中xxx
可以動態地設置到正在處理的文件,如在問題問)。
不知道爲什麼這被認爲是解決方案。處理程序確定日誌目標,格式化程序確定日誌格式;這兩個可以被認爲是正交的。如果我想臨時更改特定記錄器的日誌格式(例如記錄器'package1.module2')以添加一些特定於模塊的上下文信息,我希望爲記錄器的所有處理程序執行此操作。枚舉所有其他記錄器可能使用的處理程序,臨時更改格式,然後將其更改回來以免打破其他記錄器,這不是一個解決方案。 – dtheodor
這確實是在這種更極端的情況下必須要做的事情,在這種情況下,人們幾乎無法控制處理程序在記錄器中的分佈情況。這是一個具體而不幸的案例。現在,這樣做仍然可以按照這個答案完成,所以對我來說看起來很好(免責聲明:我都問過這個問題並提供了這個答案)。有趣的是在上面的評論中針對案例大綱提出具體問題,並附上相應的具體答案;這屬於另一個StackOverflow條目。 – EOL
有幾種方法。除了already documented ones(extra
參數記錄調用,LoggerAdapter
,Filter
)之外,另一種方法是指定一個自定義格式類,其實例可以隨時瞭解正在處理的文件。例如:
class FileProcessingFormatter(logging.Formatter):
def __init__(self, fmt, datefmt=None, current_file=None):
super(FileProcessingFormatter, self).__init__(fmt, datefmt)
self.orig_fmt = fmt
self.current_file = current_file
def format(self, record):
if self.current_file is None:
self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__', '')
else:
self._fmt = self.orig_fmt.replace('__FILE_PLACEHOLDER__',
' while processing %r' % self.current_file)
return super(FileProcessingFormatter, self).format(record)
實例化格式化......
f = FileProcessingFormatter('%(levelname)s__FILE_PLACEHOLDER__ %(message)s')
for h in relevant_handlers:
h.setFormatter(f)
進程文件...
f.current_file = fn
process_file(fn)
f.current_file = None
這是非常簡單的 - 例如,而不是在線程環境,如果使用文件處理由不同的線程同時完成。
更新:儘管根記錄器的處理程序可通過logging.getLogger().handlers
訪問,但這是可能更改的實現細節。由於您的要求不是那麼基本,您可以使用dictConfig()
來配置您的日誌記錄(可通過針對舊版Python的logutils項目進行配置)。
我更新了我的答案。 –