13

私は次のようにファイルを解析しようとします:

[account]
User = first

[account]
User = second

PythonでConfigParserを使用していますが、ファイルを読み取ると次のようになります。

Config = configparser.ConfigParser()
Config.read(file)
print (Config.sections())

エラーがあります:

While reading from ... : section 'account' already exists

このファイルを解析するにはどうすればよいですか?他に図書館はありますか?(python3を優先)

4

4 に答える 4

27

同じ名前のセクションを単純にマージする(最新のセクションが優先される)場合は、strict=Falseオプションをコンストラクター(Python 3.2で追加)に渡すだけです。dict.update()重複するセクションがにマージされると、効果的に動作を取得できます。

Config = configparser.ConfigParser(strict=False)

ただし、OPのサンプルデータから、データの損失を回避するために、同じ名前のセクションを分離しておく必要があることは明らかです。ConfigParser読み取ったセクションを辞書に格納するため、同じ名前の複数のセクションを処理することはできません。幸い、コンストラクターは、dict_type辞書のような別のオブジェクトを指定できる引数を受け入れます。これを使用して、同じ名前のセクションをサポートできます。これは、セクション名が以前に見られたときに一意の番号を追加することによってセクション名を壊す大まかな解決策です。

from collections import OrderedDict

class multidict(OrderedDict):
    _unique = 0   # class variable

    def __setitem__(self, key, val):
        if isinstance(val, dict):
            self._unique += 1
            key += str(self._unique)
        OrderedDict.__setitem__(self, key, val)

Config = configparser.ConfigParser(defaults=None, dict_type=multidict, strict=False)

少しの作業で、よりクリーンなソリューションを構築できるはずです。

于 2012-03-27T11:36:13.300 に答える
1

残念ながら、提供されたiniファイルの形式は標準に従って正しくありません。セクションの名前は、ドキュメント内で一意である必要があります。

ファイル形式を変更できる場合(私はすでに読んでいますが、完全を期すために...)、次のような解決策が適切です。

[accounts]
keys= account1, account2

[account1]
User = first

[account2]
User = second

ファイルの形式を実際に変更できない場合は、構成ファイルを手動で解析するしか選択肢がないのではないかと思います。

于 2012-03-27T11:14:58.003 に答える
1

「RFC標準から逸脱して独自の構成フォーマットを作成する場合は、独自のパーサーを作成する必要があります。」このhttp://www.tek-tips.com/viewthread.cfm?qid=1110829は私のために働いた。いくつかの小さな変更を加えました。**投稿時にフォーマットが正しく表示されませんでした

def configToDict(file):
# open the file
file = open('settings.cfg')

# create an empty dict
sections = {}

for line in file.readlines():
    # get rid of the newline
    line = line[:-1]
    try:
        # this will break if you have whitespace on the "blank" lines
        if line:
            # skip comment lines
            if line[0] == '#': next
            # this assumes everything starts on the first column
            if line[0] == '[':
                # strip the brackets
                section = line[1:-1]
                # create a new section if it doesn't already exist
                if not sections.has_key(section):
                    sections[section] = {}
            else:
                # split on first the equal sign
                (key, val) = line.split('=', 1)
                # create the attribute as a list if it doesn't
                # exist under the current section, this will
                # break if there's no section set yet
                if not sections[section].has_key(key):
                    sections[section][key] = []
                # append the new value to the list
                sections[section][key].append(val)
    except Exception as e:
        print str(e) + "line:" +line
return sections
于 2017-03-24T14:20:25.277 に答える
1

最新のPythonには、必要な処理を実行できるオプションがあります。 ConfigParser(strict=True)

Cf:https ://docs.python.org/3/library/configparser.html#configparser.ConfigParser

于 2017-04-21T18:27:57.263 に答える