Вход, StreamHandler и стандартные потоки

Я не могу выяснить, как зарегистрировать сообщения информационного уровня к stdout, но все остальное к stderr. Я уже прочитал этот http://docs.python.org/library/logging.html. Какое-либо предложение?

62
задан 5 September 2009 в 16:45

3 ответа

Самый простой обработчик для отправки окрашенный выводом к stderr:

class ColorStderr(logging.StreamHandler):
    def __init__(self):
        class AddColor(logging.Formatter):
            def format(self, record: logging.LogRecord):
                msg = super().format(record)
                # Green/Cyan/Yellow/Red/Redder based on log level:
                color = '\033[1;' + ('32m', '36m', '33m', '31m', '41m')[
                   min(4,int(4 * record.levelno / logging.FATAL))]
                return color + record.levelname + '\033[1;0m: ' + msg
        super().__init__(sys.stderr)
        self.setFormatter(AddColor())

Использование с:

logging.basicConfig(level=logging.INFO, handlers=[ColorStderr()])

Или можно даже применить средство форматирования непосредственно к текущему обработчику журналов без потребности в ColorStderr:

logging.getLogger().handlers[0].setFormatter(AddColor())
1
ответ дан 31 October 2019 в 13:54

Попробуйте этот тест ~~

import sys
import logging
import threading

def _logging_handle(self, record):
    self.STREAM_LOCKER = getattr(self, "STREAM_LOCKER", threading.RLock())
    if self.stream in (sys.stdout, sys.stderr) and record.levelname in self.FIX_LEVELS:
        try:
            self.STREAM_LOCKER.acquire()
            self.stream = sys.stdout
            self.old_handle(record)
            self.stream = sys.stderr
        finally:
            self.STREAM_LOCKER.release()
    else:
        self.old_handle(record)


def patch_logging_stream(*levels):
    """
    writing some logging level message to sys.stdout

    example:
    patch_logging_stream(logging.INFO, logging.DEBUG)
    logging.getLogger('root').setLevel(logging.DEBUG)

    logging.getLogger('root').debug('test stdout')
    logging.getLogger('root').error('test stderr')
    """
    stream_handler = logging.StreamHandler
    levels = levels or [logging.DEBUG, logging.INFO]
    stream_handler.FIX_LEVELS = [logging.getLevelName(i) for i in levels]
    if hasattr(stream_handler, "old_handle"):
        stream_handler.handle = stream_handler.old_handle
    stream_handler.old_handle = stream_handler.handle
    stream_handler.handle = _logging_handle

патча обезьяны

#
patch_logging_stream(logging.INFO, logging.DEBUG)
logging.getLogger('root').setLevel(logging.DEBUG)

logging.getLogger('root').debug('test root stdout')
logging.getLogger('root').error('test root stderr')

тестовый вывод

$ python3 test_patch_logging.py 2>/dev/null
DEBUG:root:test root stdout

$ python3 test_patch_logging.py 1>/dev/null
ERROR:root:test root stderr

0
ответ дан 31 October 2019 в 13:54

Так как мое редактирование было отклонено, вот мой ответ. ответ @goncalopp хорош, но не делает одинокий или работает из поля. Вот моя улучшенная версия:

import sys, logging


class LogFilter(logging.Filter):
    """Filters (lets through) all messages with level < LEVEL"""
    # http://stackoverflow.com/a/24956305/408556
    def __init__(self, level):
        self.level = level

    def filter(self, record):
        # "<" instead of "<=": since logger.setLevel is inclusive, this should
        # be exclusive
        return record.levelno < self.level

MIN_LEVEL = logging.DEBUG
stdout_hdlr = logging.StreamHandler(sys.stdout)
stderr_hdlr = logging.StreamHandler(sys.stderr)
log_filter = LogFilter(logging.WARNING)
stdout_hdlr.addFilter(log_filter)
stdout_hdlr.setLevel(MIN_LEVEL)
stderr_hdlr.setLevel(max(MIN_LEVEL, logging.WARNING))
# messages lower than WARNING go to stdout
# messages >= WARNING (and >= STDOUT_LOG_LEVEL) go to stderr

rootLogger = logging.getLogger()
rootLogger.addHandler(stdout_hdlr)
rootLogger.addHandler(stderr_hdlr)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# Example Usage
>>> logger.debug("A DEBUG message")
>>> logger.info("An INFO message")
>>> logger.warning("A WARNING message")
>>> logger.error("An ERROR message")
>>> logger.critical("A CRITICAL message")
10
ответ дан 31 October 2019 в 13:54

Другие вопросы по тегам:

Похожие вопросы: