如何在我自己的代码中更改日志记录配置,而不触及(上游)模块中的代码?

How to change logging configuration from within my own code, without touching the code in the (upstream) module?

此代码演示了如何从我的 class 中记录内容。它是我在名为 mptools 的模块中找到的内容的简化版本。现在我想在我的项目中使用这种日志记录,连同 mptools 模块。我怎样才能保留使日志记录到 syslog 在我自己的代码本地和模块外部工作的更改?

#=======标记之间的代码在模块内部,其余代码在我自己的代码中。

#=======
# module code here
import functools
import sys
import logging
from logging import config
#=======
# my own code here
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(module)s P%(process)d T%(thread)d %(message)s'
        },
    },
    'handlers': {
        'stdout': {
            'class': 'logging.StreamHandler',
            'stream': sys.stdout,
            'formatter': 'verbose',
        },
        'sys-logger6': {
            'class': 'logging.handlers.SysLogHandler',
            "address": ["127.0.0.1", 514],
            'facility': "local6",
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'my-logger': {
            'handlers': ['sys-logger6', 'stdout'],
            'level': logging.DEBUG,
            'propagate': True,
        },
    }
}

config.dictConfig(LOGGING)

my_logger = logging.getLogger('my-logger')

#=======
# module code here
def _logger(level, msg, exc_info=None):
    my_logger.log(level, f'{msg}', exc_info=exc_info)
    # the original code in the module uses logging.log() here.


class ContextManager:
    def __init__(self):
        self.log = functools.partial(_logger, "init")

    def __enter__(self):
        self.log(logging.ERROR, f"entering...")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            self.log(logging.ERROR, f"Exception: {exc_val}", exc_info=(exc_type, exc_val, exc_tb))
        else:
            self.log(logging.DEBUG, f"no exception, peaceful end")
#=======
# my own code here

def main():
    with ContextManager() as ctx:
        ctx.log(logging.INFO, f"running in main")


if __name__ == "__main__":
    #logging.basicConfig(level=logging.DEBUG)  # this is in the example code of the module, most likely to set the global log level
    main()

还请就如何调整此问题的标题提出建议,以便增加对 code-extraction 或 code-seperation 感兴趣的其他人的用处。

由于该模块使用 logging.log(),它会将日志直接发送到根记录器。模块这样做不是最佳实践,但可以解决。基本上你只需要将你的处理程序添加到根记录器而不是创建你自己的命名记录器。

import logging

LOGGING = {
    'version': 1,
    'handlers': {
        'sys-logger6': {
            'class': 'logging.handlers.SysLogHandler',
            "address": ["127.0.0.1", 514],
            'facility': "local6",
        },
    },
    'root': {
            'handlers': ['sys-logger6'],
            'level': logging.DEBUG,
    }
}

logging.config.dictConfig(LOGGING)

logging.log(logging.INFO, "this log will be sent to syslog")