如何ConfigParse文件保持相同键的多个值?

Ale*_*lex 12 python configparser python-2.7

我需要能够使用它ConfigParser来读取同一个键的多个值.示例配置文件:

[test]
foo = value1
foo = value2
xxx = yyy
Run Code Online (Sandbox Code Playgroud)

使用"标准"使用时ConfigParser,将有一个foo具有该值的键value2.但我需要解析器读入两个值.

重复键上输入后,我创建了以下示例代码:

from collections import OrderedDict
from ConfigParser import RawConfigParser

class OrderedMultisetDict(OrderedDict):
    def __setitem__(self, key, value):

        try:
            item = self.__getitem__(key)
        except KeyError:
            super(OrderedMultisetDict, self).__setitem__(key, value)
            return

        print "item: ", item, value
        if isinstance(value, list):
            item.extend(value)
        else:
            item.append(value)
        super(OrderedMultisetDict, self).__setitem__(key, item)


config = RawConfigParser(dict_type = OrderedDict)
config.read(["test.cfg"])
print config.get("test",  "foo")
print config.get("test",  "xxx")

config2 = RawConfigParser(dict_type = OrderedMultisetDict)
config2.read(["test.cfg"])
print config2.get("test",  "foo")
print config.get("test",  "xxx")
Run Code Online (Sandbox Code Playgroud)

第一部分(含config)在配置文件中读取我们"平常",只留下value2作为值foo(覆盖/删除等价值),我得到以下,预期的输出:

value2
yyy
Run Code Online (Sandbox Code Playgroud)

第二部分(config2)使用我的方法将多个值附加到列表,但输出是

['value1', 'value2', 'value1\nvalue2']
['yyy', 'yyy']
Run Code Online (Sandbox Code Playgroud)

我如何摆脱重复的价值观?我期待输出如下:

['value1', 'value2']
yyy
Run Code Online (Sandbox Code Playgroud)

要么

['value1', 'value2']
['yyy']
Run Code Online (Sandbox Code Playgroud)

(我不介意每个值都在列表中......).欢迎任何建议.

Nat*_*usa 13

经过一个小小的修改,我就能达到你想要的效果:

class MultiOrderedDict(OrderedDict):
    def __setitem__(self, key, value):
        if isinstance(value, list) and key in self:
            self[key].extend(value)
        else:
            super(MultiOrderedDict, self).__setitem__(key, value)
            # super().__setitem__(key, value) in Python 3

config = ConfigParser.RawConfigParser(dict_type=MultiOrderedDict)
config.read(['a.txt'])
print config.get("test",  "foo")
print config.get("test",  "xxx")
Run Code Online (Sandbox Code Playgroud)

输出:

['value1', 'value2']
['yyy']
Run Code Online (Sandbox Code Playgroud)

  • @bgStack15 你应该将 `strict` 设置为 `False`,像这样:`config = configparser.RawConfigParser(dict_type=MultiOrderedDict, strict=False)` (3认同)
  • 这似乎返回带有换行符的值而不是 2.6/2.7 的数组 (2认同)
  • 我正在使用 3.7,我也得到了一个由 '\n' 分隔的字符串,它似乎与返回的 configparser.SectionProxy 相关。 (2认同)

小智 8

接受的答案会中断config.sections(),它始终返回一个空列表(使用 Python 3.5.3 进行测试)。替换super(OrderedDict, self).__setitem__(key, value)super().__setitem__(key, value)修复了这个问题,但现在config.get(section, key)返回一个连接字符串,不再是字符串列表。

我的解决方案是:

class ConfigParserMultiValues(collections.OrderedDict):

    def __setitem__(self, key, value):
        if key in self and isinstance(value, list):
            self[key].extend(value)
        else:
            super().__setitem__(key, value)

    @staticmethod
    def getlist(value):
        return value.split(os.linesep)

    config = configparser.ConfigParser(strict=False, empty_lines_in_values=False, dict_type=ConfigParserMultiValues, converters={"list": ConfigParserMultiValues.getlist})
    ...
    values = config.getlist("Section", "key") # => ["value1", "value2"]
Run Code Online (Sandbox Code Playgroud)

配置 INI 文件接受重复的键:

[Section]
    key = value1
    key = value2
Run Code Online (Sandbox Code Playgroud)

  • 我修复了接受的答案中错误的 super() 调用,并且sections() 现在可以工作。 (2认同)

小智 6

在 python 3.8 中你还需要添加strict=False

class MultiOrderedDict(OrderedDict):
    def __setitem__(self, key, value):
        if isinstance(value, list) and key in self:
            self[key].extend(value)
        else:
            super().__setitem__(key, value)

config = ConfigParser.RawConfigParser(dict_type=MultiOrderedDict, strict=False)
config.read(['a.txt'])
print config.get("test",  "foo")
print config.get("test",  "xxx")
Run Code Online (Sandbox Code Playgroud)