【问题标题】:logger.info / logger.error with logger.addHandler - how to split streams?logger.info / logger.error 和 logger.addHandler - 如何拆分流?
【发布时间】:2017-05-10 17:13:53
【问题描述】:

所以我将.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())

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

【问题讨论】:

  • 请注意,您设置的是 logger 的级别,而不是单个处理程序。你可能想调查一下。
  • @aib:但是我正在设置各个处理程序的级别?

标签: python logging stringio


【解决方案1】:

这可以通过使用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))

【讨论】:

  • 谢谢,这行得通!采用您的方法,我压缩了您的 filter 函数并添加了 logging.Filter 的子类:ideone.com/IjG471 - 欢迎您进行编辑以反映这一点。
猜你喜欢
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
  • 2020-01-08
  • 2020-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多