【问题标题】:How to set up multiple loggers with different settings using logging.config.dictConfig()如何使用 logging.config.dictConfig() 设置具有不同设置的多个记录器
【发布时间】:2019-08-11 15:23:15
【问题描述】:

我正在尝试使用 dictConfig 设置三个不同的记录器,由于某种原因,最后一个记录器似乎总是覆盖在它之前创建的两个记录器的配置。这是我正在使用的代码:

import logging
import logging.config

def setup_logger(name, level, ContentFormat='%(asctime)s %(levelname)s %(message)s', DateTimeFormat='%Y-%m-%d %H:%M:%S'):
    logging.config.dictConfig({
        'version': 1,
        'disable_existing_loggers': True,
        'formatters': {
            'default': {'format': ContentFormat, 'datefmt': DateTimeFormat},
        },
        'handlers': {
            'console': {
                'class': 'logging.StreamHandler',
                'level': level,
                'formatter': 'default',
                'stream': 'ext://sys.stdout'
            }
        },
        'loggers': {
            'a': {
                'level': level,
                'handlers': ['console']
            },
            'b': {
                'level': level,
                'handlers': ['console']
            },
            'c': {
                'level': level,
                'handlers': ['console']
            }
        }
    })
    return logging.getLogger(name)

logger_a = setup_logger(name='a', level=logging.INFO, ContentFormat='A: %(message)s')
logger_b = setup_logger(name='b', level=logging.INFO, ContentFormat='B: %(message)s')
logger_c = setup_logger(name='c', level=logging.INFO, ContentFormat='C: %(message)s')

logger_a.info('logger_a')
logger_b.info('logger_b')
logger_b.info('logger_c')

这是输出:

C: logger_a
C: logger_b
C: logger_c

相反,我希望看到的是:

A: logger_a
B: logger_b
C: logger_c

任何想法我做错了什么?我什至尝试过制作多个处理程序,但仍然遇到同样的问题。

我有这个函数的另一个版本,它使用以下代码,我可以多次调用它来创建具有不同设置的多个单独的记录器,但我真的想弄清楚如何使用 dictConfig 来做到这一点,或者至少明白我哪里错了:

logger = logging.getLogger(name)
logger.setLevel(level)

# create console handler for printing logging output to the screen as well
formatter = logging.Formatter(ContentFormat, DateTimeFormat)
handler = logging.StreamHandler()
handler.setLevel(level)
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger

【问题讨论】:

    标签: python-3.x logging


    【解决方案1】:

    这是因为您创建并覆盖了全局配置 3 次。您使用default 格式化程序来配置特定的记录器,最后一个C 用于记录您的记录。

    您可以使用以下代码轻松检查:

    def setup_logger(name, level, DateTimeFormat='%Y-%m-%d %H:%M:%S'):
        cfg = {
            'version': 1,
            'disable_existing_loggers': False,
            'formatters': {
                'default_for_a': {'format': 'A: %(message)s', 'datefmt': DateTimeFormat},
                'default_for_b': {'format': 'B: %(message)s', 'datefmt': DateTimeFormat},
                'default_for_c': {'format': 'C: %(message)s', 'datefmt': DateTimeFormat}
            },
            'handlers': {
                'console_for_a': {
                    'class': 'logging.StreamHandler',
                    'level': level,
                    'formatter': 'default_for_a',
                    'stream': 'ext://sys.stdout'
                },
                'console_for_b': {
                    'class': 'logging.StreamHandler',
                    'level': level,
                    'formatter': 'default_for_b',
                    'stream': 'ext://sys.stdout'
                },
                'console_for_c': {
                    'class': 'logging.StreamHandler',
                    'level': level,
                    'formatter': 'default_for_c',
                    'stream': 'ext://sys.stdout'
                },
            },
            'loggers': {
                'a': {
                    'level': level,
                    'handlers': ['console_for_a']
                },
                'b': {
                    'level': level,
                    'handlers': ['console_for_b']
                },
                'c': {
                    'level': level,
                    'handlers': ['console_for_c']
                }
            }
        }
        logging.config.dictConfig(cfg)
        return logging.getLogger(name)
    
    
    logger_a = setup_logger(name='a', level=logging.INFO)
    logger_b = setup_logger(name='b', level=logging.INFO)
    logger_c = setup_logger(name='c', level=logging.INFO)
    
    logger_a.info('logger_a')
    logger_b.info('logger_b')
    logger_c.info('logger_c')
    

    或者用代码让它更通用

    import logging
    import logging.config
    
    
    def setup_logger(name, level, ContentFormat='%(asctime)s %(levelname)s %(message)s', DateTimeFormat='%Y-%m-%d %H:%M:%S'):
        cfg = {
            'version': 1,
            'disable_existing_loggers': False,
            'formatters': {
                f'default_for_{name}': {'format': ContentFormat, 'datefmt': DateTimeFormat}
            },
            'handlers': {
                f'console_for_{name}': {
                    'class': 'logging.StreamHandler',
                    'level': level,
                    'formatter': f'default_for_{name}',
                    'stream': 'ext://sys.stdout'
                },
            },
            'loggers': {
                name: {
                    'level': level,
                    'handlers': [f'console_for_{name}']
                }
            }
        }
        logging.config.dictConfig(cfg)
        return logging.getLogger(name)
    
    
    logger_a = setup_logger(name='a', level=logging.INFO, ContentFormat='A: %(message)s')
    logger_b = setup_logger(name='b', level=logging.INFO, ContentFormat='B: %(message)s')
    logger_c = setup_logger(name='c', level=logging.INFO, ContentFormat='C: %(message)s')
    
    logger_a.info('logger_a')
    logger_b.info('logger_b')
    logger_c.info('logger_c')
    

    输出是:

    A: logger_a
    B: logger_b
    C: logger_c
    

    【讨论】:

    • Ohhhhh.... 我没有意识到您只需调用一次即可配置所有内容(或者像上一个示例一样,多次使用变量)。这很有帮助!
    • 当我尝试您的示例时,它似乎不喜欢 f 字符串作为格式化程序的 ID:文件“logger.py”,第 10 行 f'default_for_{name}': {' format': ContentFormat, 'datefmt': DateTimeFormat} ^ SyntaxError: invalid syntax - 语法错误箭头指向 {name} 中的第一个括号
    • @Mike 你用的是什么版本的 Python?此语法从 3.6 开始可用。如果您使用较低的 python 3 版本,则必须将表达式替换为旧版本的字符串格式。以"{name}".format(name=name) 为例。
    • 啊... 3.5 - 我将其切换为格式化字符串并修复了它。谢谢!
    猜你喜欢
    • 2016-11-14
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    相关资源
    最近更新 更多