Экспорт с алфавитным видом в Python ConfigParser

Там какое-либо решение состоит в том, чтобы вынудить RawConfigParser.write () метод экспортировать файл конфигурации с алфавитным видом?

Даже если исходный/загруженный файл конфигурации отсортирован, модуль смешивает раздел и опции в разделы произвольно, и является действительно раздражающим для редактирования вручную огромного неотсортированного файла конфигурации.

PD: я использую python 2.6

6
задан Htechno 31 December 2009 в 09:59
поделиться

2 ответа

Три решения:

  1. Pass in a dict type (второй аргумент конструктору), который возвращает ключи в предпочитаемом вами порядке сортировки.
  2. Extend the class and overload write() (просто скопируйте этот метод из исходного кода и модифицируйте его).
  3. Скопируйте файл ConfigParser.py и добавьте сортировку в метод write().

Смотрите эту статью для упорядоченного диктата или, может быть, используйте эту реализацию , которая сохраняет исходный порядок добавления.

.
3
ответ дан 17 December 2019 в 00:10
поделиться

Первый способ выглядел как наиболее простой и безопасный.

Но, посмотрев исходный код ConfigParser, он создает пустой встроенный dict, а затем копирует все значения из «второго параметра» одно за другим. Это означает, что он не будет использовать тип OrderedDict. Легким решением может быть перегрузка класса CreateParser.

class OrderedRawConfigParser(ConfigParser.RawConfigParser):
    def __init__(self, defaults=None):
        self._defaults = type(defaults)() ## will be correct with all type of dict.
        self._sections = type(defaults)()
        if defaults:
            for key, value in defaults.items():
                self._defaults[self.optionxform(key)] = value

Остается только один недостаток ... а именно в ConfigParser.items (). odict не поддерживает обновление и сравнение с обычными dicts.

Обходной путь (перегрузите и эту функцию):

    def items(self, section):
        try:
            d2 = self._sections[section]
        except KeyError:
            if section != DEFAULTSECT:
                raise NoSectionError(section)
            d2 = type(self._section)()  ## Originally: d2 = {}
        d = self._defaults.copy()
        d.update(d2)  ## No more unsupported dict-odict incompatibility here.
        if "__name__" in d:
            del d["__name__"]
        return d.items()

Другим решением проблемы с элементами является изменение функции odict.OrderedDict.update - возможно, это проще, чем эта, но я оставляю ее тебе.

PS: Я реализовал это решение, но оно не работает. Если я выясню, что ConfigParser все еще смешивает порядок записей, я сообщу об этом.

PS2: Решено. Функция чтения в ConfigParser - идиот. В любом случае, нужно было изменить только одну строку - и некоторые другие для перегрузки во внешний файл:

def _read(self, fp, fpname):

    cursect = None
    optname = None
    lineno = 0
    e = None
    while True:
        line = fp.readline()
        if not line:
            break
        lineno = lineno + 1
        if line.strip() == '' or line[0] in '#;':
            continue
        if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
            continue
        if line[0].isspace() and cursect is not None and optname:
            value = line.strip()
            if value:
                cursect[optname] = "%s\n%s" % (cursect[optname], value)
        else:
            mo = self.SECTCRE.match(line)
            if mo:
                sectname = mo.group('header')
                if sectname in self._sections:
                    cursect = self._sections[sectname]
                ## Add ConfigParser for external overloading
                elif sectname == ConfigParser.DEFAULTSECT:
                    cursect = self._defaults
                else:
                    ## The tiny single modification needed
                    cursect = type(self._sections)() ## cursect = {'__name__':sectname}
                    cursect['__name__'] = sectname
                    self._sections[sectname] = cursect
                optname = None
            elif cursect is None:
                raise ConfigParser.MissingSectionHeaderError(fpname, lineno, line) 
                ## Add ConfigParser for external overloading.
            else:
                mo = self.OPTCRE.match(line)
                if mo:
                    optname, vi, optval = mo.group('option', 'vi', 'value')
                    if vi in ('=', ':') and ';' in optval:
                        pos = optval.find(';')
                        if pos != -1 and optval[pos-1].isspace():
                            optval = optval[:pos]
                    optval = optval.strip()
                    if optval == '""':
                        optval = ''
                    optname = self.optionxform(optname.rstrip())
                    cursect[optname] = optval
                else:
                    if not e:
                        e = ConfigParser.ParsingError(fpname)
                        ## Add ConfigParser for external overloading
                    e.append(lineno, repr(line))
    if e:
        raise e

Поверьте мне, я не писал эту вещь. Я скопировал его полностью из ConfigParser.py

Итак, что в целом делать?

  1. Загрузите odict.py по одной из ранее предложенных ссылок
  2. Импортируйте его.
  3. Скопируйте и вставьте эти коды в свой любимый utils.py (который создаст для вас класс OrderedRawConfigParser )
  4. cfg = utils.OrderedRawConfigParser (odict.OrderedDict ())
  5. используйте cfg как всегда. он останется заказанным.
  6. Устройтесь поудобнее, выкурите хаванну, расслабьтесь.

PS3: Проблема, которую я решил здесь, есть только в Python 2.5. В версии 2.6 для этого уже есть решение. Они создали второй специальный параметр в функции __ init __ , который является настраиваемым dict_type.

Таким образом, этот обходной путь требуется только для версии 2.5

1
ответ дан 17 December 2019 в 00:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: