Списки в ConfigParser
типичный сгенерированный ConfigParser файл выглядит так:
[Section]
bar=foo
[Section 2]
bar2= baz
теперь, есть ли способ индексировать списки, например:
[Section 3]
barList={
item1,
item2
}
вопрос: уникальные ключи ConfigParser Python для каждого раздела
11 ответов:
ничто не мешает вам упаковать список в строку с разделителями, а затем распаковать его, как только вы получите строку из конфигурации. Если вы сделали это таким образом ваш раздел Конфигурация будет выглядеть так:
[Section 3] barList=item1,item2это не очень красиво, но это функционально для большинства простых списков.
также немного поздно, но, возможно, полезно для некоторых. Я использую комбинацию ConfigParser и JSON:
[Foo] fibs: [1,1,2,3,5,8,13]просто прочитайте его с:
>>> json.loads(config.get("Foo","fibs")) [1, 1, 2, 3, 5, 8, 13]вы даже можете разбить строки, Если ваш список длинный (спасибо @peter-smit):
[Bar] files_to_check = [ "/path/to/file1", "/path/to/file2", "/path/to/another file with space in the name" ]конечно, я мог бы просто использовать JSON, но я нахожу файлы конфигурации гораздо более читаемыми, а раздел [DEFAULT] очень удобен.
опоздание на эту вечеринку, но я недавно реализовал это с помощью специального раздела В файле конфигурации для списка:
[paths] path1 = /some/path/ path2 = /another/path/ ...и с помощью
config.items( "paths" )чтобы получить итерационный список элементов пути, например:path_items = config.items( "paths" ) for key, path in path_items: #do something with pathнадеюсь, это поможет другим людям погуглить этот вопрос;)
одна вещь, которую многие люди не знают, это то, что разрешены многострочные значения конфигурации. Например:
;test.ini [hello] barlist = item1 item2значение
config.get('hello','barlist')теперь будет:"\nitem1\nitem2"который вы легко можете разделить с помощью метода splitlines (не забудьте отфильтровать пустые элементы).
если мы посмотрим на большую структуру, такую как пирамида, они используют эту технику:
def aslist_cronly(value): if isinstance(value, string_types): value = filter(None, [x.strip() for x in value.splitlines()]) return list(value) def aslist(value, flatten=True): """ Return a list of strings, separating the input based on newlines and, if flatten=True (the default), also split on spaces within each line.""" values = aslist_cronly(value) if not flatten: return values result = [] for value in values: subvalues = value.split() result.extend(subvalues) return resultСам, я бы может и продлить ConfigParser если это обычная вещь для вас:
class MyConfigParser(ConfigParser): def getlist(self,section,option): value = self.get(section,option) return list(filter(None, (x.strip() for x in value.splitlines()))) def getlistint(self,section,option): return [int(x) for x in self.getlist(section,option)]обратите внимание, что есть несколько вещей, чтобы искать при помощи этой техники
- новые линии товаров должна начинаться с пробела (например, пробел или табуляция)
- все следующие строки, начинающиеся с пробела считаются частью предыдущего пункта. Также, если он имеет знак = или если он начинается с a ; после пробела.
если вы хотите буквально проходить в список, то вы можете использовать:
конфигурация:ast.literal_eval()[section] option=["item1","item2","item3"]код:
import ConfigParser import ast my_list = ast.literal_eval(config.get("section", "option")) print(type(my_list)) print(my_list)выход:
<type'list'> ["item1","item2","item3"]
Я приземлился здесь, чтобы потреблять это...
[global] spys = [email protected], [email protected]ответ состоит в том, чтобы разделить его на запятую и очистить пробелы:
SPYS = [e.strip() for e in parser.get('global', 'spys').split(',')]чтобы получить результат списка:
['[email protected]', '[email protected]']это может не ответить на вопрос ОП точно, но может быть простой ответ, который некоторые люди ищут.
это то, что я использую для списков:
конфигурационный файл содержимое:
[sect] alist = a b cкод :
l = config.get('sect', 'alist').split('\n')это работает для строк
в случае цифры
конфигурации содержания:
nlist = 1 2 3код:
nl = config.get('sect', 'alist').split('\n') l = [int(nl) for x in nl]спасибо.
только примитивные типы поддерживаются для сериализации с помощью синтаксического анализатора конфигурации. Я бы использовал JSON или YAML для такого рода требований.
я столкнулся с той же проблемой в прошлом. Если вам нужны более сложные списки, подумайте о создании собственного парсера путем наследования от ConfigParser. Затем вы бы перезаписали метод get следующим образом:
def get(self, section, option): """ Get a parameter if the returning value is a list, convert string value to a python list""" value = SafeConfigParser.get(self, section, option) if (value[0] == "[") and (value[-1] == "]"): return eval(value) else: return valueС помощью этого решения вы сможете определить словари в файле config.
но будьте осторожны! Это не так безопасно: это означает, что любой может запустить код через ваш файл конфигурации. Если безопасность не является проблемой в вашем проекте, я бы рассмотрел использование непосредственно классы python в виде файлов конфигурации. Следующее является гораздо более мощным и расходным, чем файл ConfigParser:
class Section bar = foo class Section2 bar2 = baz class Section3 barList=[ item1, item2 ]
import ConfigParser import os class Parser(object): """attributes may need additional manipulation""" def __init__(self, section): """section to retun all options on, formatted as an object transforms all comma-delimited options to lists comma-delimited lists with colons are transformed to dicts dicts will have values expressed as lists, no matter the length """ c = ConfigParser.RawConfigParser() c.read(os.path.join(os.path.dirname(__file__), 'config.cfg')) self.section_name = section self.__dict__.update({k:v for k, v in c.items(section)}) #transform all ',' into lists, all ':' into dicts for key, value in self.__dict__.items(): if value.find(':') > 0: #dict vals = value.split(',') dicts = [{k:v} for k, v in [d.split(':') for d in vals]] merged = {} for d in dicts: for k, v in d.items(): merged.setdefault(k, []).append(v) self.__dict__[key] = merged elif value.find(',') > 0: #list self.__dict__[key] = value.split(',')так что теперь мой
config.cfgфайл, который может выглядеть так:[server] credentials=username:admin,password:<r3t loggingdirs=/tmp/logs,~/logs,/var/lib/www/logs timeoutwait=15можно разобрать на мелкозернистые-достаточно объектов для моего небольшого проекта.
>>> import config >>> my_server = config.Parser('server') >>> my_server.credentials {'username': ['admin'], 'password', ['<r3t']} >>> my_server.loggingdirs: ['/tmp/logs', '~/logs', '/var/lib/www/logs'] >>> my_server.timeoutwait '15'Это для очень быстрого разбора простых конфигураций, вы теряете все возможности для извлечения ints, bools и других типов вывода без преобразования объекта, возвращаемого из
Parser, или повторное выполнение работы синтаксического анализа, выполненной классом синтаксического анализатора в другом месте.
json.нагрузки и АСТ.literal_eval, кажется, работает, но простой список в конфигурации обрабатывает каждый символ как байт, поэтому возвращает даже квадратную скобку....
значение если config имеет значение fieldvalue = [1,2,3,4,5]
затем config.читать.*(контекстно-свободная грамматика) config ['fieldValue'] [0] возвращение " ["вместо 1
Comments