Как отключить и снова включить ведение журнала консоли в Python?

Я использую модуль Python logging и хочу на некоторое время отключить ведение журнала консоли, но он не работает.

#!/usr/bin/python
import logging

logger = logging.getLogger() # this gets the root logger
# ... here I add my own handlers 
#logger.removeHandler(sys.stdout)
#logger.removeHandler(sys.stderr)

print logger.handlers 
# this will print [<logging.StreamHandler instance at ...>]
# but I may have other handlers there that I want to keep

logger.debug("bla bla")

Приведенный выше код отображает bla bla на стандартный вывод, и я не знаю, как можно безопасно отключить обработчик консоли. Как я могу быть уверен, что я временно удаляю консоль StreamHandler, а не другую?

Ответ 1

Я нашел решение для этого:

logger = logging.getLogger('my-logger')
logger.propagate = False
# now if you use logger it will not log to console.

Это предотвратит отправку журнала в верхний регистратор, который включает ведение журнала консоли.

Ответ 2

Я использую:

logger = logging.getLogger()
logger.disabled = True
... whatever you want ...
logger.disabled = False

Ответ 3

Вы можете использовать:

logging.basicConfig(level=your_level)

где ваш_уровень является одним из следующих:

      'debug': logging.DEBUG,
      'info': logging.INFO,
      'warning': logging.WARNING,
      'error': logging.ERROR,
      'critical': logging.CRITICAL

Итак, если вы установите your_level на logging.CRITICAL, вы получите только критические сообщения, отправленные:

logging.critical('This is a critical error message')

Настройка your_level на logging.DEBUG отобразит все уровни ведения журнала.

Подробнее см. примеры ведения журнала.

Таким же образом, чтобы изменить уровень для каждого обработчика, используйте функцию Handler.setLevel().

import logging
import logging.handlers

LOG_FILENAME = '/tmp/logging_rotatingfile_example.out'

# Set up a specific logger with our desired output level
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)

# Add the log message handler to the logger
handler = logging.handlers.RotatingFileHandler(
          LOG_FILENAME, maxBytes=20, backupCount=5)

handler.setLevel(logging.CRITICAL)

my_logger.addHandler(handler)

Ответ 4

(длинный мертвый вопрос, но для будущих искателей)

Ближе к исходному коду/намерению плаката, это работает для меня под python 2.6

#!/usr/bin/python
import logging

logger = logging.getLogger() # this gets the root logger

lhStdout = logger.handlers[0]  # stdout is the only handler initially

# ... here I add my own handlers 
f = open("/tmp/debug","w")          # example handler
lh = logging.StreamHandler(f)
logger.addHandler(lh)

logger.removeHandler(lhStdout)

logger.debug("bla bla")

У меня возникла необходимость убрать обработчик stdout после добавления нового; появляется код регистратора для автоматического повторного добавления stdout, если нет обработчиков.

Ответ 5

Контекстный менеджер

import logging 
class DisableLogger():
    def __enter__(self):
       logging.disable(logging.CRITICAL)
    def __exit__(self, a, b, c):
       logging.disable(logging.NOTSET)

Пример использования:

with DisableLogger():
    do_something()

Ответ 6

Чтобы полностью отключить ведение журнала:

logging.disable(sys.maxint) # Python 2

logging.disable(sys.maxsize) # Python 3

Чтобы включить ведение журнала:

logging.disable(logging.NOTSET)

Другие ответы обеспечивают обходные пути, которые не полностью решают проблему, такие как

logging.getLogger().disabled = True

и для некоторых n больше 50

logging.disable(n)

Проблема с первым решением заключается в том, что он работает только для корневого регистратора. Другие регистраторы, созданные, скажем, с помощью logging.getLogger(__name__), не отключаются этим методом.

Второе решение влияет на все журналы. Но он ограничивает выходной уровень уровнями выше указанного, поэтому его можно переопределить, войдя в систему с уровнем, превышающим 50.

Это можно предотвратить с помощью

logging.disable(sys.maxint)

насколько я могу судить (после просмотра источника), это единственный способ полностью отключить ведение журнала.

Ответ 7

Здесь есть несколько действительно хороших ответов, но, по-видимому, простейшие не принимаются слишком много внимания (только от infinito).

root_logger = logging.getLogger()
root_logger.disabled = True

Это отключает корневой журнал и, следовательно, все остальные регистраторы. Я не тестировал, но должен быть и самым быстрым.

Из кода регистрации в python 2.7 я вижу это

def handle(self, record):
    """
    Call the handlers for the specified record.

    This method is used for unpickled records received from a socket, as
    well as those created locally. Logger-level filtering is applied.
    """
    if (not self.disabled) and self.filter(record):
        self.callHandlers(record)

Это означает, что когда он отключен, не вызывается обработчик, и он должен быть более эффективным, чтобы фильтрация была очень высокой, или, например, установка обработчика no-op.

Ответ 8

Не нужно переадресовывать stdout. Вот лучший способ сделать это:

import logging
class MyLogHandler(logging.Handler):
    def emit(self, record):
        pass

logging.getLogger().addHandler(MyLogHandler())

Еще проще:

logging.getLogger().setLevel(100)

Ответ 9

Я не очень хорошо знаю модуль протоколирования, но я использую его так, как обычно, я хочу отключить только отладочные (или информационные) сообщения. Вы можете использовать Handler.setLevel(), чтобы установить уровень ведения журнала на CRITICAL или выше.

Кроме того, вы можете заменить sys.stderr и sys.stdout файлом, открытым для записи. См. http://docs.python.org/library/sys.html#sys. stdout. Но я бы не рекомендовал этого.

Ответ 10

Вы также можете:

handlers = app.logger.handlers
# detach console handler
app.logger.handlers = []
# attach
app.logger.handlers = handlers

Ответ 11

import logging

log_file = 'test.log'
info_format = '%(asctime)s - %(levelname)s - %(message)s'
logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'info_format': {
            'format': info_format
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'info_format'
        },
        'info_log_file': {
            'class': 'logging.handlers.RotatingFileHandler',
            'level': 'INFO',
            'filename': log_file,
            'formatter': 'info_format'
        }
    },
    'loggers': {
        '': {
            'handlers': [
                'console',
                'info_log_file'
            ],
            'level': 'INFO'
        }
    }
})


class A:

    def __init__(self):
        logging.info('object created of class A')

        self.logger = logging.getLogger()
        self.console_handler = None

    def say(self, word):
        logging.info('A object says: {}'.format(word))

    def disable_console_log(self):
        if self.console_handler is not None:
            # Console log has already been disabled
            return

        for handler in self.logger.handlers:
            if type(handler) is logging.StreamHandler:
                self.console_handler = handler
                self.logger.removeHandler(handler)

    def enable_console_log(self):
        if self.console_handler is None:
            # Console log has already been enabled
            return

        self.logger.addHandler(self.console_handler)
        self.console_handler = None


if __name__ == '__main__':
    a = A()
    a.say('111')
    a.disable_console_log()
    a.say('222')
    a.enable_console_log()
    a.say('333')

Вывод на консоль:

2018-09-15 15:22:23,354 - INFO - object created of class A
2018-09-15 15:22:23,356 - INFO - A object says: 111
2018-09-15 15:22:23,358 - INFO - A object says: 333

Содержимое файла test.log:

2018-09-15 15:22:23,354 - INFO - object created of class A
2018-09-15 15:22:23,356 - INFO - A object says: 111
2018-09-15 15:22:23,357 - INFO - A object says: 222
2018-09-15 15:22:23,358 - INFO - A object says: 333

Ответ 12

Если вы хотите временно отключить определенный регистратор, вот что было сделано.

Журнал примеров

2019-10-02 21:28:45,663 django.request PID: 8  Internal Server Error: /service_portal/get_all_sites

Код

django_request_logger = logging.getLogger('django.request')
django_request_logger.disabled = True
django_request_logger.disabled = False

Ответ 13

подкласс обработчик, который вы хотите временно отключить:

class ToggledHandler(logging.StreamHandler):
"""A handler one can turn on and off"""

def __init__(self, args, kwargs):
    super(ToggledHandler, self).__init__(*args, **kwargs)
    self.enabled = True  # enabled by default

def enable(self):
    """enables"""
    self.enabled = True

def disable(self):
    """disables"""
    self.enabled = False

def emit(self, record):
    """emits, if enabled"""
    if self.enabled:
        # this is taken from the super emit, implement your own
        try:
            msg = self.format(record)
            stream = self.stream
            stream.write(msg)
            stream.write(self.terminator)
            self.flush()
        except Exception:
            self.handleError(record)

найти обработчик по имени довольно просто:

_handler = [x for x in logging.getLogger('').handlers if x.name == your_handler_name]
if len(_handler) == 1:
    _handler = _handler[0]
else:
    raise Exception('Expected one handler but found {}'.format(len(_handler))

однажды найден:

_handler.disable()
doStuff()
_handler.enable()