在python中解析具有相同节名的配置文件

时间:2012-03-26 16:34:54

标签: python python-3.x configparser

我尝试解析文件:

[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 个答案:

答案 0 :(得分:15)

如果你想要的只是简单地合并相同名称的部分(最新的一个获胜),只需将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)

通过一些工作,你应该能够构建一个更清洁的解决方案。

答案 1 :(得分:2)

在最新的python上有一个选项可以做你想要的: ConfigParser(strict=True)

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

答案 2 :(得分:1)

不幸的是,根据标准,提供的ini文件的格式不正确。部分的名称在文档中必须是唯一的。

如果您可以更改文件格式(我已经读过您不能,但为了完整性......),那么这样的解决方案是合适的:

[accounts]
keys= account1, account2

[account1]
User = first

[account2]
User = second

如果你真的无法替换文件的格式,那么我担心你唯一的选择是手动解析配置文件。

答案 3 :(得分:0)

” 如果您偏离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