3
[loggers]
keys=root

[handlers]
keys=consoleHandler,errorHandler,debugHandler

[formatters]
keys=errorFormatter,debugFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler,errorHandler,debugHandler
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=debugFormatter
args=(sys.stdout,)

[handler_errorHandler]
class=FileHandler
level=ERROR
formatter=errorFormatter
args=('errors.log',)

[handler_debugHandler]
class=FileHandler
level=DEBUG
formatter=debugFormatter
args=('debugs.log',)

[formatter_errorFormatter]
style={
format=
    {asctime} - {name} - {levelname} - line {lineno} - {message}
datefmt=%d/%m/%y - %H:%M:%S

[formatter_debugFormatter]
style={
format={asctime} - {name} - {levelname} - {message}
datefmt=%d/%m/%y - %H:%M:%S

如果我有一个像上面这样的配置文件,我怎样才能访问它debugHandler以便我可以这样做debugHandler.addFilter(my_custom_filter)

我实际上是在尝试将DEBUG消息发送到debugs.logERROR消息发送到errors.log,但目前ERROR还发送了debugs.log我不想要的消息。现在,基于这个 StackOverflow 帖子,这可以通过过滤器实现,但为了添加过滤器,我需要一个logging.Handler对象,但我不知道如何获得一个对象。

提前谢谢:~)

4

1 回答 1

1

是的,您需要在 debug_handler 上使用过滤器,但是您不能通过fileConfig添加过滤器。

从文档:

fileConfig() API 比 dictConfig() API 更老,并且不提供涵盖日志记录某些方面的功能。例如,您不能使用 fileConfig() 配置过滤器对象,这些对象提供超过简单整数级别的消息过滤。如果您需要在日志配置中包含 Filter 的实例,则需要使用 dictConfig()。请注意,未来对配置功能的增强将添加到 dictConfig(),因此在方便时考虑转换到这个更新的 API 是值得的。

因此,请考虑使用dictConfig(无论您的配置如何,都没有理由不切换到dictConfig dictConfig,因为它更好、更新、更灵活,并且将添加所有未来的好东西)。

所以你的配置,过渡到dictConfig看起来像这样(这可以被粘贴和测试):

import logging
from logging import config

class FileFilter:
    """Allow only LogRecords whose severity levels are below ERROR."""

    def __call__(self, log):
        if log.levelno < logging.ERROR:
            return 1
        else:
            return 0


logging_config = {
    'version': 1,
    'formatters': {
        'error_formatter': {
            'format': '{asctime} - {name} - {levelname} - line {lineno} - {message}',
            'style': '{',
            'datefmt': '%d/%m/%y - %H:%M:%S',
        },
        'debug_formatter': {
            'format': '{asctime} - {name} - {levelname} - {message}',
            'style': '{',
            'datefmt': '%d/%m/%y - %H:%M:%S',
        },
    },
    'filters': {
        'file_filter': {
            '()': FileFilter,
        },
    },
    'handlers': {
        'console_handler': {
            'class': 'logging.StreamHandler',
            'formatter': 'debug_formatter',
        },
        'error_handler': {
            'class': 'logging.FileHandler',
            'formatter': 'debug_formatter',
            'level': 'ERROR',
            'filename': 'errors.log',
        },
        'debug_handler': {
            'class': 'logging.FileHandler',
            'formatter': 'debug_formatter',
            'filters': ['file_filter'],
            'filename': 'debug.log',
        },
    },
    'root': {
        'level': 'DEBUG',
        'handlers': ['console_handler', 'error_handler', 'debug_handler'],
    },
}

config.dictConfig(logging_config)

logger = logging.getLogger(__name__)

# these get logged to the console and only to the debugs.log file
# if you want just the debug messages logged to the file, adjust the filter
logger.debug('this is a debug message')
logger.info('this is an info message')
logger.warning('this is a warning message')

# this get logged to the console and only to the errors.log file
logger.error('this is an error message')
logger.critical('this is a critical message')

这将输出:

27/09/19 - 07:52:44 - __main__ - DEBUG - this is a debug message  # also to debug.log
27/09/19 - 07:52:44 - __main__ - INFO - this is an info message  # also to debug.log
27/09/19 - 07:52:44 - __main__ - WARNING - this is a warning message  # also to debug.log
27/09/19 - 07:52:44 - __main__ - ERROR - this is an error message  # also to errors.log but not to debug.log
27/09/19 - 07:52:44 - __main__ - CRITICAL - this is a critical message  # also to errors.log but not to debug.log

如果您出于某种神秘原因(我看不到任何原因)坚持使用较旧的 API,fileConfig请参阅此答案,该答案使用自定义格式化程序,可实现相同的目的,无需过滤器。

于 2019-09-27T04:58:25.503 回答