logging - 合并多个配置文件

时间:2016-09-20 14:29:10

标签: python python-2.7

我正在开发一个项目,我们有一个加载多个插件的核心应用程序。 每个插件都有自己的配置文件,核心应用程序也有一个。

我们正在使用python标准库中的优秀日志记录模块。 日志记录模块包括从.ini文件加载日志记录配置的功能。 但是,如果加载另一个配置文件,则会丢弃其他文件,并且仅使用新配置。

我想要做的是将我的日志配置拆分为多个文件,以便应用程序可以加载自己的配置文件,然后加载每个插件将其日志配置合并到主要配置文件中。

注意:fileConfig有一个名为disable_existing_loggers的选项,可以设置为False。但是,这只会使现有的记录器保持活动状态,但它仍然会清除处理程序的内部映射(这意味着插件的配置不能使用应用程序配置文件中定义的处理程序)。

我可以手动合并文件以生成我自己的配置,但我宁愿避免这种情况。

感谢。

为了更清楚,我想做这样的事情:

# application.ini
[loggers]
keys=root,app
[handlers]
keys=rootHandler,appHandler
[formatters]
keys=myformatter

[logger_root]
# stuff
[handler_rootHandler]
# stuff
[formatter_myformatter]
# stuff

...

# plugin.ini
[loggers]
keys=pluginLogger  # no root logger
[handlers]
keys=pluginHandler  # no root handler
# no formatters section

[logger_pluginLogger]
# stuff
formatter=myformatter # using the formatter from application.ini

2 个答案:

答案 0 :(得分:1)

我找不到办法去做我想做的事情,所以我最后还是上了一堂课去做。

这是一个方便的github gist

答案 1 :(得分:1)

我通常使用 logging.config.dictConfig pyYaml 包执行此操作。该程序包允许您将配置文件的内容作为 dict 对象加载。

唯一需要的是一个小助手类来处理配置覆盖/附加组件:

import yaml


class Configuration(dict):
def __init__(self,
             config_file_path=None,
             overwrites=None):

    with open(config_file_path) as config_file:
        config = yaml.load(config_file)

    super(Configuration, self).__init__(config)

    if overwrites is not None:
        for overwrite_key, value in overwrites.items():
            self.apply_overwrite(self, overwrite_key, value)

def apply_overwrite(self, node, key, value):
    if isinstance(value, dict):
        for item in value:
            self.apply_overwrite(node[key], item, value[item])
    else:
        node[key] = value

例如,如果您的主要配置是:

logger:
  version: 1
  disable_existing_loggers: False

  formatters:
      simple:
          format: '%(levelname)s: Module: %(name)s Msg: %(message)s'

  handlers:
      file:
          level: DEBUG
          class: logging.handlers.RotatingFileHandler
          maxBytes: 10000000
          backupCount: 50
          formatter: simple
          filename: '/tmp/log1.log'

  root:
      handlers: [file]
      level: DEBUG

,你的覆盖是:

logger:
  handlers:
      file:
          filename: '/tmp/log2.log'

你可以像这样得到你的覆盖记录器:

from configuration import Configuration
from logging.config import dictConfig
import logging


if __name__ == '__main__':
    config = Configuration('standard.yml', overwrites=Configuration('overwrite.yml'))
    dictConfig(config['logger'])
    logger = logging.getLogger(__name__)
    logger.info('I logged it')