logger.info / logger.error 和 logger.addHandler - 如何拆分流?
logger.info / logger.error with logger.addHandler - how to split streams?
所以我将 .info
放在一个 StringIO 中,将 .error
放在另一个 StringIO 中。
如何阻止它们同时被放入两者?
序曲:
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())
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
这可以通过使用 Filter 来实现。由于过滤器函数是一个任意的布尔函数(出于某种原因 returns zero/nonzero),您可以让它过滤级别的最小值和最大值:
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))
所以我将 .info
放在一个 StringIO 中,将 .error
放在另一个 StringIO 中。
如何阻止它们同时被放入两者?
序曲:
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())
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
这可以通过使用 Filter 来实现。由于过滤器函数是一个任意的布尔函数(出于某种原因 returns zero/nonzero),您可以让它过滤级别的最小值和最大值:
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))