2008-12-02 4 views

ответ

89

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

[Section 3] 
barList=item1,item2 

Это не очень, но функционально для большинства простых списков.

+5

Так работает файл конфигурации протокола Python. – 2008-12-03 00:02:46

+2

И если у вас есть сложные списки, вы можете обратиться к этому вопросу: http://stackoverflow.com/questions/330900/how-to-quickly-parse-a-list-of-strings :-) – 2008-12-03 01:06:01

+0

приятное решение , но как это сделать, если нет возможного разделителя, чем вы можете гарантировать, не появится внутри элемента списка ??? – wim 2012-02-27 23:23:19

2

Поддерживаются только примитивные типы для сериализации с помощью парсер конфигурации. Я бы использовал JSON или YAML для такого рода требований.

+0

спасибо за разъяснение, utku. единственная проблема заключается в том, что я не могу использовать внешние пакеты на данный момент. Я думаю, что я напишу простой класс, чтобы справиться с этим. я поделюсь им в конце концов. – pistacchio 2008-12-02 22:44:23

+0

Какую версию Python вы используете? Модуль JSON поставляется с 2.6. – 2008-12-03 00:11:20

2

Я столкнулся с той же проблемой в прошлом. Если вам нужны более сложные списки, подумайте о создании собственного анализатора, наследуя его от 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 

С помощью данного решения вы также сможете определить словарей в вашем конфигурационном файле.

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

class Section 
    bar = foo 
class Section2 
    bar2 = baz 
class Section3 
    barList=[ item1, item2 ] 
+0

Я думал об этом, однако: почему бы не установить значения конфигурации, например `barList = item1, item2`, а затем вызвать` if value.find (' , ')> 0: return value.split (', ') `или еще лучше, попросите приложение проанализировать все параметры конфигурации в виде списков и просто` .split (', ') `все вслепую? – Droogans 2012-10-31 16:53:11

76

опоздание к этой партии, но я недавно внедренная это с помощью специальной секции в файле конфигурации для списка:

[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 

Надеется, что это помогает другой люду погуглить этот вопрос;)

139

Также немного поздно, но, возможно, полезно для некоторых. Я использую комбинацию ConfigParser и JSON:

[Foo] 
fibs: [1,1,2,3,5,8,13] 

просто читать его:

>>> json.loads(config.get("Foo","fibs")) 
[1, 1, 2, 3, 5, 8, 13] 

Вы можете даже разбить строки, если ваш список длинный (спасибо @ питер-Smit):

[Bar] 
files_to_check = [ 
    "/path/to/file1", 
    "/path/to/file2", 
    "/path/to/another file with space in the name" 
    ] 

Конечно, я мог бы просто использовать JSON, но я могу найти файлы конфигурации, более читаемые, а раздел [DEFAULT] очень удобен.

50

Одна вещь, о которой многие люди не знают, заключается в том, что допускаются многострочные значения конфигурации.Например:

;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 

Source

Myself, я бы, возможно продлить ConfigParser если это обычное дело для вас:

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

  1. Новые строки, которые являются элементами, должны начинаться с пробелов (например, пробел или вкладку)
  2. Все следующие строки, начинающиеся с пробелов, считаются частью предыдущего элемента. Также, если у него есть знак = или он начинается с; следуя пробелу.
1
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:$3<r3t 
loggingdirs=/tmp/logs,~/logs,/var/lib/www/logs 
timeoutwait=15 

Может быть проанализирован в мелкозернистых-достаточно объектов для моего небольшого проекта.

>>> import config 
>>> my_server = config.Parser('server') 
>>> my_server.credentials 
{'username': ['admin'], 'password', ['$3<r3t']} 
>>> my_server.loggingdirs: 
['/tmp/logs', '~/logs', '/var/lib/www/logs'] 
>>> my_server.timeoutwait 
'15' 

Это очень быстрого разборе простых конфигов, вы потеряете все возможности для извлечения Интса, Bools и других видов продукции либо без преобразования объекта, возвращаемым из Parser или повторного выполнения работы синтаксического анализа проделанной класс Parser в другом месте.

22

Если вы хотите буквально проход в списке, то вы можете использовать:

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"] 
14

Я приземлился здесь, пытаясь уничтожить это ...

[global] 
spys = [email protected], [email protected] 

Ответ разделить ее на запятую и раздеть пространства:

SPYS = [e.strip() for e in parser.get('global', 'spys').split(',')] 

Чтобы получить результат списка:

['[email protected]', '[email protected]'] 

Он не может ответить на вопрос OP в точности, но может быть простым ответом, который ищут некоторые люди.

6

Это то, что я использую для списков:

конфигурации содержимого файла:

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

спасибо.

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