Programming

ConfigParser의 목록

procodes 2020. 6. 8. 21:50
반응형

ConfigParser의 목록


일반적인 ConfigParser 생성 파일은 다음과 같습니다.

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

이제 다음과 같은 목록을 색인화하는 방법이 있습니까?

[Section 3]
barList={
    item1,
    item2
}

관련 질문 : 섹션 당 Python의 ConfigParser 고유 키


목록을 구분 된 문자열로 포장 한 다음 구성에서 문자열을 얻으면 압축을 풀지 않습니다. 이 방법으로 설정하면 구성 섹션은 다음과 같습니다.

[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. 공백으로 시작하는 다음 줄은 모두 이전 항목의 일부로 간주됩니다. 또한 = 기호가 있거나;로 시작하는 경우; 공백을 따르십시오.

당신이 할 경우 말 그대로 목록을 전달 당신은 사용할 수 있습니다 :

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 = richard.sorge@cccp.gov, mata.hari@deutschland.gov

대답은 쉼표로 나누고 공백을 제거하는 것입니다.

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

목록 결과를 얻으려면

['richard.sorge@cccp.gov', 'mata.hari@deutschland.gov']

OP의 질문에 정확하게 대답하지는 않지만 일부 사람들이 찾고있는 간단한 답변 일 수 있습니다.


이 답변 중 하나 에 대한 converterskwarg에 대한ConfigParser() 언급 은 오히려 실망 스럽습니다.

문서에 따르면 파서 및 섹션 프록시 모두 ConfigParser에 대한 get방법을 추가하는 사전을 전달할 수 있습니다 . 따라서 목록의 경우 :

example.ini

[Germ]
germs: a,list,of,names, and,1,2, 3,numbers

파서 예제 :

cp = ConfigParser(converters={'list': lambda x: [i.strip() for i in x.split(',')]})
cp.read('example.ini')
cp.getlist('Germ', 'germs')
['a', 'list', 'of', 'names', 'and', '1', '2', '3', 'numbers']
cp['Germ'].getlist('germs')
['a', 'list', 'of', 'names', 'and', '1', '2', '3', 'numbers']

This is my personal favorite as no subclassing is necessary and I don't have to rely on an end user to perfectly write JSON or a list that can be interpreted by ast.literal_eval.


This is what I use for lists:

config file content:

[sect]
alist = a
        b
        c

code :

l = config.get('sect', 'alist').split('\n')

it work for strings

in case of numbers

config content:

nlist = 1
        2
        3

code:

nl = config.get('sect', 'alist').split('\n')
l = [int(nl) for x in nl]

thanks.


Only primitive types are supported for serialization by config parser. I would use JSON or YAML for that kind of requirement.


I faced the same problem in the past. If you need more complex lists, consider creating your own parser by inheriting from ConfigParser. Then you would overwrite the get method with that:

    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

With this solution you will also be able to define dictionaries in your config file.

But be careful! This is not as safe: this means anyone could run code through your config file. If security is not an issue in your project, I would consider using directly python classes as config files. The following is much more powerful and expendable than a ConfigParser file:

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(',')

So now my config.cfg file, which could look like this:

[server]
credentials=username:admin,password:$3<r3t
loggingdirs=/tmp/logs,~/logs,/var/lib/www/logs
timeoutwait=15

Can be parsed into fine-grained-enough objects for my small project.

>>> 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'

This is for very quick parsing of simple configs, you lose all ability to fetch ints, bools, and other types of output without either transforming the object returned from Parser, or re-doing the parsing job accomplished by the Parser class elsewhere.


json.loads & ast.literal_eval seems to be working but simple list within config is treating each character as byte so returning even square bracket....

meaning if config has fieldvalue = [1,2,3,4,5]

then config.read(*.cfg) config['fieldValue'][0] returning [ in place of 1


I completed similar task in my project with section with keys without values:

import configparser

# allow_no_value param says that no value keys are ok
config = configparser.ConfigParser(allow_no_value=True)

# overwrite optionxform method for overriding default behaviour (I didn't want lowercased keys)
config.optionxform = lambda optionstr: optionstr

config.read('./app.config')

features = list(self.config['FEATURES'].keys())

print(features)

Output:

['BIOtag', 'TextPosition', 'IsNoun', 'IsNomn']

app.config:

[FEATURES]
BIOtag
TextPosition
IsNoun
IsNomn

참고URL : https://stackoverflow.com/questions/335695/lists-in-configparser

반응형