Списки в ConfigParser



типичный сгенерированный ConfigParser файл выглядит так:



[Section]
bar=foo
[Section 2]
bar2= baz


теперь, есть ли способ индексировать списки, например:



[Section 3]
barList={
item1,
item2
}


вопрос: уникальные ключи ConfigParser Python для каждого раздела

448   11  

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)]

обратите внимание, что есть несколько вещей, чтобы искать при помощи этой техники

  1. новые линии товаров должна начинаться с пробела (например, пробел или табуляция)
  2. все следующие строки, начинающиеся с пробела считаются частью предыдущего пункта. Также, если он имеет знак = или если он начинается с 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

    Ничего не найдено.