Уникальные ключи Python ConfigParser для каждого раздела

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

>>> from ConfigParser import ConfigParser
>>> from StringIO import StringIO
>>> fh = StringIO("""
... [Some Section]
... spam: eggs
... spam: ham
... """)
>>> parser = ConfigParser()
>>> parser.readfp(fh)
>>> print parser.items('Some Section')
[('spam', 'ham')]

Затем я вернулся и нашел ту часть документов, которую должен был прочитать:

Разделы обычно хранятся во встроенном словаре. Альтернативный тип словаря может быть передан в конструктор ConfigParser. Например, если передан тип словаря, который сортирует свои ключи, разделы будут отсортированы при обратной записи, как и ключи в каждом разделе.

Чтобы сохранить мою существующую схему файла конфигурации (которая мне действительно нравится сейчас), я думаю о передаче объекта, подобного отображению, как упомянуто выше, который накапливает значения вместо того, чтобы забивать их. Есть ли более простой способ предотвратить коллапс ключ / значение, который я пропускаю? Вместо создания сумасшедшего адаптера (который может сломаться, если ConfigParserизменения в реализации) я должен просто написать вариант ConfigParser сам?

Я чувствую, что это может быть один из тех "скучных" моментов, когда я вижу только сложные решения.

[Edit:] Вот более точный пример того, как я хотел бы использовать один и тот же ключ несколько раз:

[Ignored Paths]
ignore-extension: .swp
ignore-filename: tags
ignore-directory: bin

Мне не нравится синтаксис с разделителями-запятыми, потому что это трудно на глаза, когда вы масштабируете его до многих значений; например, список из пятидесяти расширений, разделенных запятыми, не будет особенно удобочитаемым.

2 ответа

Решение

ConfigParser не предназначен для обработки таких условий. Кроме того, ваш файл конфигурации не имеет смысла для меня.

ConfigParser дает вам структуру, похожую на dict, для каждого раздела, поэтому, когда вы вызываете parser.items(section), я ожидаю аналогичного вывода для dict.items(), который является просто списком кортежей ключ / значение. Я бы никогда не ожидал увидеть что-то вроде:

[('spam', 'eggs'), ('spam', 'ham')]

Не говоря уже о том, как бы вы себя ожидали?

parser.get('Some Section', 'spam')

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

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

[Some Section]
spam: eggs, ham

И это в вашем коде:

spam_values = [v.strip() for v in parser.get('Some Section', 'spam').split(',')]

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

РЕДАКТИРОВАТЬ: Если вы не возражаете против дополнительной зависимости, вы можете проверить ConfigObj, который изначально поддерживает списки в качестве типа значения.

Этот недостаток ConfigParser является причиной, по которой pyglet использовал исправленную версию epydoc для замены ini ConfigParser следующим простым форматом:

name: pyglet
url: http://www.pyglet.org/

output: html
target: doc/api/
...    
module: pyglet

exclude: pyglet.gl.gl
exclude: pyglet.gl.agl
exclude: pyglet.gl.lib_agl
exclude: pyglet.gl.wgl
...

Если вам не нужны разделы - этот подход может быть полезным.

Другие вопросы по тегам