logger.info/logger.error与logger.addHandler - 如何拆分流?

问题描述:

所以我把.info放在一个StringIO中,.error放在另一个StringIO中。logger.info/logger.error与logger.addHandler - 如何拆分流?

我该如何阻止它们同时进入两者?

前奏:

from __future__ import print_function 

import logging 

from io import IOBase 
from sys import stdout 
from platform import python_version_tuple 

if python_version_tuple()[0] == '3': 
    from IO import StringIO 
else: 
    try: 
     from cStringIO import StringIO 
    except ImportError: 
     from StringIO import StringIO 

代码:

# Some other file, like __init__.py 
logging.basicConfig(
     format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', level='INFO') 
handler = logging.root.handlers.pop() 
assert logging.root.handlers == [], "root logging handlers aren't empty" 
handler.stream.close() 
handler.stream = stdout 
logging.root.addHandler(handler) 
# Some other file, like __init__.py 

log = logging.getLogger(__name__) 
stderr_stream = logging.StreamHandler(StringIO()) 
log.addHandler(stderr_stream) 
log.setLevel(logging.ERROR) 
print('log.level =', {logging.INFO: 'INFO', 
         logging.ERROR: 'ERROR'}[log.level]) 

stdout_stream = logging.StreamHandler(StringIO()) 
log.addHandler(stdout_stream) 
log.setLevel(logging.INFO) 
print('log.level =', {logging.INFO: 'INFO', 
         logging.ERROR: 'ERROR'}[log.level]) 

log.info('hello') 
log.error('world') 
print('stderr_stream =', stderr_stream.stream.getvalue()) 
print('stdout_stream =', stdout_stream.stream.getvalue()) 

http://ideone.com/Nj6Asz输出:

log.level = ERROR 
log.level = INFO 
2016-12-23 09:03:27,761 __main__  INFO  hello 
2016-12-23 09:03:27,761 __main__  ERROR world 
stderr_stream = hello 
world 

stdout_stream = hello 
world 
+0

注你正在设置* logger *的级别,而不是单个的处理程序。你可能想看看。 – aib

+0

@aib:但我正在设置各个处理程序的级别? –

这可以通过使用一个Filter来实现。由于过滤器的功能是任意布尔函数(返回零/非零出于某种原因)你可以把它过滤的最低水平,最大:

class LevelRangeFilter: 
    def __init__(self, min_level, max_level): 
     self._min_level = min_level 
     self._max_level = max_level 

    def filter(self, record): 
     if (
      (self._min_level is None or self._min_level <= record.levelno) 
      and 
      (self._max_level is None or record.levelno < self._max_level) 
     ): 
      return 0 
     else: 
      return 1 

...

stderr_stream.addFilter(LevelRangeFilter(logging.ERROR, None)) 
stdout_stream.addFilter(LevelRangeFilter(logging.INFO, logging.ERROR)) 
+0

谢谢,这有效!采取你的方法,我压缩了'filter'函数并添加了'logging.Filter'的子类:http://ideone.com/IjG471 - 欢迎您编辑以反映这一点。 –