【问题标题】:Python Logger : StreamHandler not controlling my terminal stdout?Python Logger:StreamHandler 不控制我的终端标准输出?
【发布时间】:2022-11-12 17:12:23
【问题描述】:

我有 - 我相信 - 一个带有两个处理程序的相当标准的记录器配置:文件和流。文件处理程序工作得非常好,我可以用自己的级别控制输出文件的内容,但是流处理程序似乎没有做任何事情,无论我是否添加 StreamHandler,所有根日志都传递到标准输出。任何人都会知道我做错了什么?

我在 Ubuntu 20.04 上运行 python3.10,这里是配置:

import logging
import sys

# root logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# terminal logger
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.CRITICAL)
logger.addHandler(stream_handler)
# file logger
file_handler = logging.FileHandler(f'logs/{__name__}.txt', 'w')
file_handler.setLevel(logging.DEBUG)
logger.addHandler(file_handler)

我试图将 sys.stdout 作为 StreamHandler() 的参数传递,但它没有改变结果。 有了上面的内容,我希望控制台只打印 CRITICAL 但它显示所有级别:

DEBUG:network:deserialized data: ['111', 'idle', 'normal']
INFO:network:ID:100 ['normal'] already exists, storing server_states[587]: (-13, 2890, 35, 69)
DEBUG:network:_entity.position.server_states={583: <rect(-17, 2713, 35, 69)>}
INFO:network:sending:100|idle['normal']|480;971;35;69|right|0|0|1000.0|3|None|0|0;0|0;0;0;0;0;0
INFO:network:received:107|idle['normal','collectable']12;2935;35;69|left|0|0|1000.0|3|None|45.1

我想知道它是否与记录器名称有关(来自模块的动态姓名) ?

【问题讨论】:

    标签: python logging python-logging


    【解决方案1】:

    您的配置应该按预期工作。这个稍作修改的脚本:

    import logging
    import sys
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    # terminal logger
    stream_handler = logging.StreamHandler(sys.stdout)
    stream_handler.setLevel(logging.CRITICAL)
    logger.addHandler(stream_handler)
    # file logger
    file_handler = logging.FileHandler(f'logs/{__name__}.txt', 'w')
    file_handler.setLevel(logging.DEBUG)
    logger.addHandler(file_handler)
    for level in (logging.DEBUG, logging.INFO, logging.WARNING,
                  logging.ERROR, logging.CRITICAL):
        if level:
            logger.log(level, "Event at %s", logging.getLevelName(level))
    

    按预期工作,如下所示:

    $ python3.10 test_71641676.py > tmp.txt
    $ more tmp.txt
    Event at CRITICAL
    

    这表明 sys.stdout 被用于 StreamHandler

    【讨论】:

      【解决方案2】:

      这似乎与我有多个模块这一事实有关——每个模块都可以有一个记录器来控制台,但主脚本必须保持控制并有自己的记录器集(我没有)。 这个页面解决了我的问题:https://docs.python.org/3/howto/logging-cookbook.html#logging-to-multiple-destinations

      【讨论】:

        【解决方案3】:

        我有同样的问题,但我不认为有多个模块或主脚本'是它的原因。我发现在我的例子中是tqdm 模块正在重置流处理程序级别(如this PR 所示)。这是我的日志记录设置,希望这可以帮助任何有同样问题的人......

        def setup_logging(logfile: Path=Path(), debug: bool=False):
            """
            Setup the logging framework
            :param logfile:     Name of the logfile
            :param debug:       Add the function name to the log-messages and set the console logging level to VERBOSE
            :return:
             """
        
            # Set the default formats
            if debug:
                fmt  = '%(asctime)s - %(name)s - %(levelname)s | %(message)s'
                cfmt = '%(levelname)s - %(name)s | %(message)s'
            else:
                fmt  = '%(asctime)s - %(levelname)s | %(message)s'
                cfmt = '%(levelname)s | %(message)s'
            datefmt  = '%Y-%m-%d %H:%M:%S'
        
            # Add a verbose logging level = 15
            logging.VERBOSE = 15
            logging.addLevelName(logging.VERBOSE, 'VERBOSE')
            logging.__all__ += ['VERBOSE'] if 'VERBOSE' not in logging.__all__ else []
            def verbose(self, message, *args, **kws):
                if self.isEnabledFor(logging.VERBOSE): self._log(logging.VERBOSE, message, args, **kws)
            logging.Logger.verbose = verbose
        
            # Add a succes logging level = 25
            logging.SUCCESS = 25
            logging.addLevelName(logging.SUCCESS, 'SUCCESS')
            logging.__all__ += ['SUCCESS'] if 'SUCCESS' not in logging.__all__ else []
            def success(self, message, *args, **kws):
                if self.isEnabledFor(logging.SUCCESS): self._log(logging.SUCCESS, message, args, **kws)
            logging.Logger.success = success
        
            # Set the root logging level
            logger = logging.getLogger()
            logger.setLevel('VERBOSE')
        
            # Add the console streamhandler and bring some color to those boring logs! :-)
            coloredlogs.install(level='VERBOSE' if debug or not logfile.name else 'INFO', fmt=cfmt, datefmt=datefmt)   # NB: Using tqdm sets the streamhandler level to 0, see: https://github.com/tqdm/tqdm/pull/1235
            coloredlogs.DEFAULT_LEVEL_STYLES['verbose']['color'] = 245  # = Gray
        
            if not logfile.name:
                return
        
            # Add the log filehandler
            logfile.parent.mkdir(parents=True, exist_ok=True)      # Create the log dir if it does not exist
            formatter  = logging.Formatter(fmt=fmt, datefmt=datefmt)
            loghandler = logging.FileHandler(logfile)
            loghandler.setLevel('VERBOSE')
            loghandler.setFormatter(formatter)
            loghandler.set_name('loghandler')
            logger.addHandler(loghandler)
        
            # Add the error/warnings filehandler
            errorhandler = logging.FileHandler(logfile.with_suffix('.errors'), mode='w')
            errorhandler.setLevel('WARNING')
            errorhandler.setFormatter(formatter)
            errorhandler.set_name('errorhandler')
            logger.addHandler(errorhandler)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-17
          • 2014-11-22
          相关资源
          最近更新 更多