web-dev-qa-db-ja.com

ConfigParserのリスト

ConfigParserで生成される一般的なファイルは次のようになります。

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

次のようなリストにインデックスを付ける方法はありますか?

[Section 3]
barList={
    item1,
    item2
}

関連質問: PythonのConfigParserセクションごとの一意のキー

149
pistacchio

リストを区切られた文字列にパックし、設定から文字列を取得したらアンパックすることを妨げるものは何もありません。この方法で設定した場合、設定セクションは次のようになります。

[Section 3]
barList=item1,item2

きれいではありませんが、ほとんどの単純なリストで機能します。

119
David Locke

また少し遅れますが、一部の人にとっては役立つかもしれません。私は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]セクションは非常に便利です。

196
quasimodo

このパーティーに遅れて来ましたが、最近、リスト用の構成ファイルの専用セクションでこれを実装しました:

[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

これが他の人々がこの質問をググリングするのに役立つことを願っています;)

90
Henry Cooke

多くの人が知らないことの1つは、複数行の構成値が許可されていることです。例えば:

;test.ini
[hello]
barlist = 
    item1
    item2

config.get('hello','barlist')の値は次のようになります。

"\nitem1\nitem2"

Splitlinesメソッドで簡単に分割できます(空のアイテムをフィルターすることを忘れないでください)。

Pyramidのような大きなフレームワークを見ると、彼らはこのテクニックを使用しています:

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. 空白で始まる次のすべての行は、前のアイテムの一部と見なされます。また、=記号がある場合、または;で始まる場合空白に続いて。
57
Peter Smit

literallyをリストに渡す場合は、次を使用できます。

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"]
33
PythonTester

これを消費しようとここに着陸しました...

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

答えは、カンマで分割してスペースを削除することです。

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

リストの結果を取得するには:

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

OPの質問に正確には答えないかもしれませんが、一部の人々が探している単純な答えかもしれません。

15
John Mee

これらの回答のいずれにおいても、 converters K_GConfigParser() についての言及はありませんでした。

ドキュメントによると、辞書を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']

サブクラス化は不要であり、ast.literal_evalで解釈できるJSONやリストを完全に記述するためにエンドユーザーに依存する必要がないため、これは私の個人的なお気に入りです。

11
Grr

これはリストに使用するものです:

構成ファイルの内容:

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

ありがとう。

8
LittleEaster

構成パーサーによるシリアル化では、プリミティブ型のみがサポートされています。この種の要件にはJSONまたはYAMLを使用します。

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 ]
2
Mapad
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'

これは、単純な構成を非常に迅速に解析するためです。Parserから返されたオブジェクトを変換したり、Parserクラスによって実行された解析ジョブを再実行したりせずに、int、bool、およびその他のタイプの出力をフェッチするすべての機能を失います他の場所。

1
Droogans

プロジェクトで、値のないキーを含むセクションを使用して、同様のタスクを完了しました。

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)

出力:

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

app.config:

[FEATURES]
BIOtag
TextPosition
IsNoun
IsNomn
0
feeeper

json.loadsast.literal_evalは機能しているようですが、config内の単純なリストでは各文字がバイトとして扱われているため、角括弧も返されます。

configにfieldvalue = [1,2,3,4,5]がある場合の意味

次にconfig.read(*.cfg)config['fieldValue'][0][の代わりに1を返します

0
Abhishek Jain