2011-07-27 45 views
9

用Python(通过日志记录模块)临时更改日志消息格式的最简单方法是什么?如何在Python中临时更改记录消息的格式?

目标是拥有一些标准的消息格式,同时能够临时添加有关正在读取的某个文件(如其名称)的信息;当文件不再被读取时,消息格式应该恢复为默认值。产生这些消息的程序是而不是意识到正在读取什么文件,所以如果它的消息自动包含相关的文件名(如果错误消息是:“ERROR ,同时读取文件 ***: ...“而不是”错误:...“)。

+0

我更新了我的答案。 –

回答

7

这是一个简单的解决方案,可以从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可以动态地设置到正在处理的文件,如在问题问)。

+0

不知道为什么这被认为是解决方案。处理程序确定日志目标,格式化程序确定日志格式;这两个可以被认为是正交的。如果我想临时更改特定记录器的日志格式(例如记录器'package1.module2')以添加一些特定于模块的上下文信息,我希望为记录器的所有处理程序执行此操作。枚举所有其他记录器可能使用的处理程序,临时更改格式,然后将其更改回来以免打破其他记录器,这不是一个解决方案。 – dtheodor

+0

这确实是在这种更极端的情况下必须要做的事情,在这种情况下,人们几乎无法控制处理程序在记录器中的分布情况。这是一个具体而不幸的案例。现在,这样做仍然可以按照这个答案完成,所以对我来说看起来很好(免责声明:我都问过这个问题并提供了这个答案)。有趣的是在上面的评论中针对案例大纲提出具体问题,并附上相应的具体答案;这属于另一个StackOverflow条目。 – EOL

6

有几种方法。除了already documented onesextra参数记录调用,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项目进行配置)。

+0

谢谢。一个只能通过'logging.basicConfig()'定义的处理程序能获得'relevant_handlers'吗?如果不是,那么如何定义'related_handlers'? – EOL

+0

感谢您的更新。我需要阅读Logging HOWTO,也许更多 - 在我可以实现任何具体解决方案之前... – EOL

相关问题