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)

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

于 2017-04-21T18:27:57.263 回答