Как отключить и повторно включить консольный вход в Python?


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

#!/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 на stdout и я не знаю, как я могу спокойно отключить обработчик консоли. Как я могу быть уверен, что временно удаляю консольный StreamHandler, а не другой?

11 110

11 ответов:

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

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

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

Я использую:

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

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

logging.basicConfig(level=your_level)

здесь your_level одна из них:

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

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

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

задание your_level до ведение журнала.Отладка показать все уровни ведения журнала.

для более подробной информации, пожалуйста, взгляните на примеры ведения журнала.

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

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

ближе к исходному коду/намерению плаката, это работает для меня под 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")

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

контекст менеджер

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()

здесь есть несколько действительно хороших ответов, но, по-видимому, самый простой не слишком учитывается (только от 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.

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

logging.disable(sys.maxint)

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

logging.disable(logging.NOTSET)

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

logging.getLogger().disabled = True

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

logging.disable(n)

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

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

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

logging.disable(sys.maxint)

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

нет необходимости отвлекать stdout. Вот лучший способ сделать это:

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

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

еще более простой способ-это:

logging.getLogger().setLevel(100)

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

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

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

handlers = app.logger.handlers
# detach console handler
app.logger.handlers = []
# attach
app.logger.handlers = handlers
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