如何使用logging.config.dictConfig()设置具有不同设置的多个记录器

Mik*_*ike 3 logging python-3.x

我正在尝试使用 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')
Run Code Online (Sandbox Code Playgroud)

这是输出:

C: logger_a
C: logger_b
C: logger_c
Run Code Online (Sandbox Code Playgroud)

相反,我想看到的是:

A: logger_a
B: logger_b
C: logger_c
Run Code Online (Sandbox Code Playgroud)

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

我有这个函数的另一个版本,它使用以下代码,我可以多次调用它来创建具有不同设置的多个单独的记录器,但我真的想弄清楚如何使用 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
Run Code Online (Sandbox Code Playgroud)

Mar*_*her 6

发生这种情况是因为您创建并覆盖了全局配置 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')
Run Code Online (Sandbox Code Playgroud)

或者用代码让它更通用

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')
Run Code Online (Sandbox Code Playgroud)

输出是:

A: logger_a
B: logger_b
C: logger_c
Run Code Online (Sandbox Code Playgroud)