2015-05-20 2 views
1

В this question OP хотел извлечь неизвестное количество разделов из файла конфигурации с помощью ConfigParser, где все разделы разделяли один и тот же внутренний формат.Как использовать ConfigParser для извлечения неизвестного числа пар значений?

В моем случае я вынужден держать все в одной секции. Я пытаюсь разработать удобный, разумный метод хранения «пар» данных. Хитрый пример объясняет вещи лучше:

[pings] 
host1 = foo.com 
port1 = 80 
interval1 = 60 
host2 = bar.com 
port2 = 8080 
interval2 = 300 
host3 = baz.com 
port3 = 443 
interval3 = 15 

Это может быть прочитано в цикле инкрементации-индексе, и как только мы достигаем итерации, где ожидаемое значение не найдено, мы можем предположить, что мы достигли конца данных и остановки. Проблема в том, что это уродливое и недостижимое, и что еще хуже, предположим, что мы хотели прокомментировать host1 ... Нам пришлось бы перенумеровать все остальное в списке, чтобы предотвратить раннее завершение сканирования.

Это не поражает меня как гораздо лучше:

[pings] 
hosts = foo.com, bar.com, baz.com 
ports = 80, 8080, 443 
intervals = 60, 300, 15 

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

я мог повернуть его:

[pings] 
ping1 = foo.com, 80, 60 
ping2 = bar.com, 8080, 300 
ping3 = baz.com, 443, 15 

Немного более логически сгруппировано, но все еще страдает от проблемы перенумерации линии, если элементы добавлены/удалены/перегруппированы. Также легко потеряться (подумайте визуально, просматривая очень широкую таблицу CSV).

Я хотел бы избежать встраивания JSON или любых формальных литералов. Слишком много возможностей для плохого редактирования для отключения парсера.

Давным-давно я помню, как работал с PHP, где вы могли добавить переменное количество элементов строки запроса, таких как ?host[]=foo.com&host[]=bar.com&host[]=baz.com, а глобальное значение $_GET['host'] стало бы массивом с тремя элементами внутри. Кража, что синтаксис, я мог бы сделать:

[pings] 
host[] = foo.com 
port[] = 80 
interval[] = 60 

host[] = bar.com 
port[] = 8080 
interval[] = 300 

host[] = baz.com 
port[] = 443 
interval[] = 15 

... или:

[pings] 
ping[] = foo.com, 80, 60 
ping[] = bar.com, 8080, 300 
ping[] = baz.com, 443, 15 

... и там будет немного меньше беспокоиться о том, когда добавление/удаление элементов. Но я верю, что на самом деле произойдет с ConfigParser - это самые последние элементы (или это самые ранние?), Чтобы перезаписать остальные ... если [] даже принят в качестве ключа конфигурации.

Есть ли какие-либо установленные рекомендации для выражения таких вещей в конфигурационных файлах?

+1

Почему ограничение только для одного раздела? В этом отношении мне кажется, что JSON или YAML были бы лучшим файловым форматом, чем файлы INI. – Waylan

+0

Если внешнее требование заставляет вас использовать INI-файл, другой формат будет намного проще в использовании. – chepner

ответ

0

Без тестирования, я бы написать что-то вроде:

config = ConfigParser.ConfigParser() 

with open('path/to/file.ini') as config_f: 
    config.readfp(config_f) 
    # config.readfile in 3.2+ 

configitems = config.section('pings') 

ping_infos = [{'host':host, 'port':port, 'interval':interval} for 
       host, port, interval in [value.split()]} for 
       key,value in configitems if key.startswith('ping')] 

Тогда вы можете написать свой конфигурационный файл, как

[pings] 
; pingANYUNIQUECHAR = hostname, portnumber, interval 
ping-foo.com = foo.com, 80, 60 
ping-bar.com = bar.com, 8080, 300 

И вы будете в конечном итоге с:

ping_infos = [{'host': 'foo.com', 
       'port': '80', 
       'interval': 60}, 
       {'host': 'bar.com', 
       'port': 8080, 
       'interval': 300}] 

 Смежные вопросы

  • Нет связанных вопросов^_^