代码之家  ›  专栏  ›  技术社区  ›  sorin

如何在Python中禁用和重新启用控制台日志记录?

  •  123
  • sorin  · 技术社区  · 16 年前

    如何禁用 logging 关于Python中的标准错误流?这不起作用:

    import logging
    
    logger = logging.getLogger()
    logger.removeHandler(sys.stderr)
    logger.warning('foobar')  # emits 'foobar' on sys.stderr
    
    12 回复  |  直到 5 年前
        1
  •  211
  •   ereOn    14 年前

    我找到了解决办法:

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

        2
  •  114
  •   infinito    16 年前

    我使用:

    logger = logging.getLogger()
    logger.disabled = True
    ... whatever you want ...
    logger.disabled = False
    
        3
  •  72
  •   vallentin Remi    5 年前

    您可以使用:

    logging.basicConfig(level=your_level)
    

    哪里 你的职业水平

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

    所以,如果你 到 日志记录。关键 ,您将只收到由以下人员发送的关键消息:

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

    背景 你的职业水平 到 日志记录.调试

    更多详情请看 logging examples.

    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
  •  49
  •   pymen    5 年前

    使用上下文管理器-[ ]

    import logging 
    
    class DisableLogger():
        def __enter__(self):
           logging.disable(logging.CRITICAL)
        def __exit__(self, exit_type, exit_value, exit_traceback):
           logging.disable(logging.NOTSET)
    

    使用示例:

    with DisableLogger():
        do_something()
    

    如果你需要[ 更复杂 ]您可以查看的细粒度解决方案 AdvancedLogger

    AdvancedLogger can be used for fine grained logging temporary modifications
    
    How it works:
    Modifications will be enabled when context_manager/decorator starts working and be reverted after
    
    Usage:
    AdvancedLogger can be used
    - as decorator `@AdvancedLogger()`
    - as context manager `with  AdvancedLogger():`
    
    It has three main functions/features:
    - disable loggers and it's handlers by using disable_logger= argument
    - enable/change loggers and it's handlers by using enable_logger= argument
    - disable specific handlers for all loggers, by using  disable_handler= argument
    
    All features they can be used together
    

    # Disable specific logger handler, for example for stripe logger disable console
    AdvancedLogger(disable_logger={"stripe": "console"})
    AdvancedLogger(disable_logger={"stripe": ["console", "console2"]})
    
    # Enable/Set loggers
    # Set level for "stripe" logger to 50
    AdvancedLogger(enable_logger={"stripe": 50})
    AdvancedLogger(enable_logger={"stripe": {"level": 50, "propagate": True}})
    
    # Adjust already registered handlers
    AdvancedLogger(enable_logger={"stripe": {"handlers": "console"}
    
        5
  •  44
  •   LAKSHYA SINGH    5 年前

    (这是一个死了很久的问题,但对于未来的搜索者来说)

    #!/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")
    

    之后 增加一个新的;如果不存在处理程序,记录器代码似乎会自动重新添加标准输出。

    如果在实例化lhStdout时遇到indexoutofound错误,请在添加文件处理程序后将实例化移动到。

    ...
    logger.addHandler(lh)
    
    lhStdout = logger.handlers[0]
    logger.removeHandler(lhStdout)
    
        6
  •  37
  •   townie starfry    7 年前

    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)
    

    据我所知 source

        7
  •  27
  •   andrea_crotti    14 年前

    这里有一些非常好的答案,但显然最简单的答案没有考虑太多(仅从无穷大)。

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

    这将禁用根记录器,从而禁用所有其他记录器。

    从python2.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)
    

        8
  •  12
  •   Géry Ogam    5 年前

    日志记录 the following structure :

    • 根据名称空间层次结构和点分隔符排列;
    • 每个记录器都有一个 ( logging.WARNING logging.NOTSET 默认情况下,对于非根记录器)和 (对于具有 日志记录.NOTSET
    • 过滤器 ;
    • 每个记录器都有一个 ;
    • 水平 (
    • 每个处理程序都有一个 过滤器

    日志记录 the following process

    Logging flow.

    1. 将记录器的级别设置为 logging.CRITICAL + 1 .

      • 使用主API:

        import logging
        
        logger = logging.getLogger("foo")
        logger.setLevel(logging.CRITICAL + 1)
        
      • import logging.config
        
        logging.config.dictConfig({
            "version": 1,
            "loggers": {
                "foo": {
                    "level": logging.CRITICAL + 1
                }
            }
        })
        
    2. 添加筛选器 lambda record: False

      • 使用主API:

        import logging
        
        logger = logging.getLogger("foo")
        logger.addFilter(lambda record: False)
        
      • import logging.config
        
        logging.config.dictConfig({
            "version": 1,
            "filters": {
                "all": {
                    "()": lambda: (lambda record: False)
                }
            },
            "loggers": {
                "foo": {
                    "filters": ["all"]
                }
            }
        })
        
    3. 删除记录器的现有处理程序, add a handler logging.NullHandler() to the logger (以防止处理程序处理事件 logging.lastResort logging.StreamHandler 使用当前流 sys.stderr 和一个水平仪 日志记录.警告 )以及 set the attribute propagate of the logger to False

      • 使用主API:

        import logging
        
        logger = logging.getLogger("foo")
        for handler in logger.handlers.copy():
            try:
                logger.removeHandler(handler)
            except ValueError:  # in case another thread has already removed it
                pass
        logger.addHandler(logging.NullHandler())
        logger.propagate = False
        
      • 使用配置API:

        import logging.config
        
        logging.config.dictConfig({
            "version": 1,
            "handlers": {
                "null": {
                    "class": "logging.NullHandler"
                }
            },
            "loggers": {
                "foo": {
                    "handlers": ["null"],
                    "propagate": False
                }
            }
        })
        

    与只防止记录事件的策略1和2相反 策略3还防止日志记录器及其祖先日志记录器的处理程序发出事件 后代伐木工人 logging.getLogger("foo.bar") )由记录器及其祖先记录器的处理程序发出。

    disabled 记录器的 True 不是另一种策略,因为它不是公共API的一部分(参见。 https://bugs.python.org/issue36318 ):

    import logging
    
    logger = logging.getLogger("foo")
    logger.disabled = True  # DO NOT DO THIS
    
        9
  •  10
  •   Ehsan Foroughi    16 年前

    不需要转移stdout。下面是更好的方法:

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

    更简单的方法是:

    logging.getLogger().setLevel(100)
    
        10
  •  1
  •   Shawn Hu    8 年前
    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
    

    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
    
        11
  •  1
  •   Andrii Ladyhin    6 年前

    这将阻止来自第三个库的所有日志记录,该库在此处描述 https://docs.python.org/3/howto/logging.html#configuring-logging-for-a-library

    logging.getLogger('somelogger').addHandler(logging.NullHandler())
    
        12
  •  0
  •   Krab    16 年前

    Handler.setLevel() 将日志记录级别设置为CRITICAL或更高。

    http://docs.python.org/library/sys.html#sys. stdout . 但我不建议这样。

        13
  •  0
  •   Italo Maia    11 年前

    handlers = app.logger.handlers
    # detach console handler
    app.logger.handlers = []
    # attach
    app.logger.handlers = handlers
    
        14
  •  0
  •   Ganesh Kalidas    6 年前

    通过更改“logging.config.dictConfig”中的一个级别,您可以将整个日志级别提升到一个新的级别。

    logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'console': {
            'format': '%(name)-12s %(levelname)-8s %(message)s'
        },
        'file': {
            'format': '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'
        }
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'console'
        },
    #CHANGE below level from DEBUG to THE_LEVEL_YOU_WANT_TO_SWITCH_FOR
    #if we jump from DEBUG to INFO
    # we won't be able to see the DEBUG logs in our logging.log file
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'formatter': 'file',
            'filename': 'logging.log'
        },
    },
    'loggers': {
        '': {
            'level': 'DEBUG',
            'handlers': ['console', 'file'],
            'propagate': False,
        },
    }
    

    })

        15
  •  0
  •   Carlos Souza    6 年前

    找到了一个优雅的解决方案 装饰工

    import logging, sys
    logger = logging.getLogger()
    logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
    
    
    def disable_debug_messages(func):
        def wrapper(*args, **kwargs):
            prev_state = logger.disabled
            logger.disabled = True
            result = func(*args, **kwargs)
            logger.disabled = prev_state
            return result
        return wrapper
    

    然后,你可以做:

    @disable_debug_messages
    def function_already_debugged():
        ...
        logger.debug("This message won't be showed because of the decorator")
        ...
    
    def function_being_focused():
        ...
        logger.debug("This message will be showed")
        ...
    

    即使你打电话 function_already_debugged function_being_focused ,调试消息来自 这样可以确保您只看到来自所关注函数的调试消息。

        16
  •  0
  •   aibrahim    6 年前

    您可以更改特定处理程序的调试模式级别,而不是完全禁用它。

    因此,如果您有一个案例,您只想停止控制台的调试模式,但仍然需要保留其他级别,如错误。你可以这样做

    # create logger
    logger = logging.getLogger(__name__)
    
    def enableConsoleDebug (debug = False):
        #Set level to logging.DEBUG to see CRITICAL, ERROR, WARNING, INFO and DEBUG statements
        #Set level to logging.ERROR to see the CRITICAL & ERROR statements only
        logger.setLevel(logging.DEBUG)
    
        debugLevel = logging.ERROR
        if debug:
            debugLevel = logging.DEBUG
    
        for handler in logger.handlers:
            if type(handler) is logging.StreamHandler:
                handler.setLevel (debugLevel)
    
    
        17
  •  -2
  •   jake77    7 年前

    子类化要临时禁用的处理程序:

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