带过滤器的日志记录
我正在使用日志记录功能(import logging
)来记录消息。
在一个模块里,我用调试级别来记录消息,像这样:my_logger.debug('msg')
。
这些调试消息有些来自于function_a()
,有些来自于function_b()
;我希望能够根据消息是来自哪个函数来开启或关闭日志记录。
我猜我需要使用日志记录的过滤机制。
有没有人能告诉我,下面的代码需要怎么修改才能实现我想要的功能?
import logging
logger = logging.getLogger( "module_name" )
def function_a( ... ):
logger.debug( "a message" )
def function_b( ... ):
logger.debug( "another message" )
if __name__ == "__main__":
logging.basicConfig( stream=sys.stderr, level=logging.DEBUG )
#don't want function_a()'s noise -> ....
#somehow filter-out function_a's logging
function_a()
#don't want function_b()'s noise -> ....
#somehow filter-out function_b's logging
function_b()
如果我把这个简单的例子扩展到更多模块和每个模块中的更多函数,我会担心会有很多记录器。
我能不能每个模块只保留一个记录器?注意,这些日志消息是“结构化”的,也就是说,如果记录日志的函数在进行某些解析工作,它们的消息前面都会有一个前缀,比如logger.debug("parsing: xxx")
- 我能不能用一行代码就关闭所有“解析”消息(不管是哪个模块或函数发出的消息)?
4 个回答
我找到了一种更简单的方法,可以在你的主脚本中使用函数:
# rm 2to3 messages
def filter_grammar_messages(record):
if record.funcName == 'load_grammar':
return False
return True
def filter_import_messages(record):
if record.funcName == 'init' and record.msg.startswith('Importing '):
return False
return True
logging.getLogger().addFilter(filter_grammar_messages) # root
logging.getLogger('PIL.Image').addFilter(filter_import_messages)
不要使用全局变量。这是个随时可能出问题的做法。
你可以给你的日志记录器起任何有意义的名字,名字之间用“.”分隔。
你可以把它们当作一个层级来管理。如果你有两个日志记录器,分别叫 a.b.c
和 a.b.d
,你可以检查 a.b
的日志级别,并同时修改这两个日志记录器。
你可以创建任意数量的日志记录器,它们的开销很小。
最常见的做法是每个模块一个日志记录器。具体可以参考 命名Python日志记录器
照这样做。
import logging
logger= logging.getLogger( "module_name" )
logger_a = logger.getLogger( "module_name.function_a" )
logger_b = logger.getLogger( "module_name.function_b" )
def function_a( ... ):
logger_a.debug( "a message" )
def function_b( ... ):
logger_b.debug( "another message" )
if __name__ == "__main__":
logging.basicConfig( stream=sys.stderr, level=logging.DEBUG )
logger_a.setLevel( logging.DEBUG )
logger_b.setLevel( logging.WARN )
... etc ...
你只需要创建一个 logging.Filter
的子类。具体可以参考这个链接:http://docs.python.org/library/logging.html#filter-objects。这个子类里会有一个方法,叫 filter(record)
,它的作用是检查日志记录,如果返回 True 就表示要记录这个日志,如果返回 False 就表示不记录。然后你可以通过调用 addFilter(filter)
方法,把这个过滤器添加到一个 Logger
或者 Handler
上。
举个例子:
class NoParsingFilter(logging.Filter):
def filter(self, record):
return not record.getMessage().startswith('parsing')
logger.addFilter(NoParsingFilter())
大概就是这样。