Конфигурационный парсер Python, который поддерживает наследование разделов? - PullRequest
12 голосов
/ 30 июня 2011

Я ищу синтаксический анализатор ini-стиля в Python, который поддерживает наследование разделов, аналогично тому, что Zend_Config_Ini делает в PHP.

Существует ли такой модуль или мне нужно будет его свернутьмой собственный?

Ответы [ 3 ]

14 голосов
/ 30 июня 2011

Python ConfigParser может загружать несколько файлов. Файлы, прочитанные позже, могут переопределить настройки из первого файла.

Например, у моего приложения есть настройки базы данных по умолчанию файл конфигурации:

[database]
server = 127.0.0.1
port = 1234
...

Я перезаписываю их на другом сервере файлом "environment.ini", содержащим тот же раздел, но разные значения:

[database]
server = 192.168.0.12
port = 2345
...

В Python:

import os
from ConfigParser import ConfigParser
dbconf = ConfigParser()
dbconf.readfp(open('default.ini'))
if os.path.exists('environment.ini'):
    dbconf.readfp(open('environment.ini'))
dbconf.get('database', 'server') # Returns 192.168.0.12
1 голос
/ 06 марта 2012

Вот что я использовал. extended_get метод - это то, что вам нужно - он поддерживает иерархические разделы.

import re
import io
import ConfigParser

class ZendConfigParser(ConfigParser.ConfigParser):
    def extended_get(self, section, key):
        if self.has_option(section, key):
            return self.get(section, key)
        else:
            orig_section, parent_section = self._get_orig_section(section)
            if orig_section != None:
                if self.has_option(orig_section,key):
                    return self.get(orig_section,key)
                else:
                    return self.extended_get(parent_section,key)
            else:
                return None



    def _get_orig_section(self, zend_section):
        orig_section = None
        parent_section = None
        for section in self.sections():
            if re.search(r'^[ \t]*' + zend_section + '\\b', section) != None:
                orig_section = section
                #look for a parent section
                match = re.match(r'\w+[ \t]*:[ \t]*(\w+)$', section)
                if match != None:
                    parent_section = match.groups()[0]
                break

        return (orig_section, parent_section)

config = ZendConfigParser()
config.read(file)
print(config.extended_get('production', 'database.params.host'))
0 голосов
/ 26 февраля 2012

Я тоже не нашел ни одного готового решения. Для ее решения я адаптировал функцию get в ConfigParser для поиска в дочернем разделе, а затем в родительском разделе:

config = SafeConfigParser()
config.read(filenames)
required_environment = "mysection"

# determine fallback requirement in case parameter is not found in required environment
fallback_environment = "default"
# loop through all sections of config files
for environment in config.sections():
    # check whether we find an inheritance based on the required section
    if re.search(required_environment + " *: *\w+", environment):
        # found inheritance, take parent as fallback section
        fallback_environment = re.sub(required_environment + r" : (\w+)", r"\1", environment)
        # take this name as requested section
        required_environment = environment

# override get method
_config_parser_get = config.get
def myConfigParserGet(id):
    # check different sections for desired value
    if config.has_option(required_environment, id):
        return _config_parser_get(required_environment, id)
    else:
        return _config_parser_get(fallback_environment, id)

config.get = myConfigParserGet

Ограничения:

  • поддерживается только доступ только для чтения к конфигурации
  • только один уровень наследования
...