我阅读了文档的一部分,发现它ConfigParser返回了一个部分中选项的键/值对列表。我认为键在一个部分中不需要是唯一的,否则解析器只会返回一个映射。我围绕这个假设设计了我的配置文件架构,然后遗憾地意识到事实并非如此:
ConfigParser
>>> from ConfigParser import ConfigParser >>> from StringIO import StringIO >>> fh = StringIO(""" ... [Some Section] ... spam: eggs ... spam: ham ... """) >>> parser = ConfigParser() >>> parser.readfp(fh) >>> print parser.items('Some Section') [('spam', 'ham')]
然后我回去找到了我应该阅读的文档部分:
部分通常存储在内置字典中。可以将替代字典类型传递给 ConfigParser 构造函数。例如,如果传递了对其键进行排序的字典类型,则这些部分将在回写时进行排序,每个部分中的键也是如此。
为了保留我现有的配置文件方案(我现在真的很喜欢;),我正在考虑传递一个如上所述的类似映射的对象,它会累积值而不是破坏它们。有没有更简单的方法来防止我缺少的键/值崩溃?而不是制作一个疯狂的适配器(如果ConfigParser实现更改可能会破坏)我应该只编写ConfigParser它本身的变体吗?
我觉得这可能是我只看到困难解决方案的那些“duh”时刻之一。
[编辑:]这是一个更精确的示例,说明我想如何多次使用同一个键:
[Ignored Paths] ignore-extension: .swp ignore-filename: tags ignore-directory: bin
我不喜欢逗号分隔列表语法,因为当您将其缩放到多个值时,它很难看;例如,五十个扩展名的逗号分隔列表将不是特别可读。
ConfigParser 并非旨在处理此类情况。此外,您的配置文件对我没有意义。
ConfigParser 为每个部分提供了一个类似 dict 的结构,因此当您调用 parser.items(section) 时,我期待与 dict.items() 类似的输出,它只是键/值元组的列表。我从没想过会看到类似的东西:
[('spam', 'eggs'), ('spam', 'ham')]
更不用说,您希望以下行为如何?:
parser.get('Some Section', 'spam')
这是检索值的预期方式。
如果你想为同一个键存储多个值,我会在你的配置文件中建议这样的东西:
[Some Section] spam: eggs, ham
这在你的代码中:
spam_values = [v.strip() for v in parser.get('Some Section', 'spam').split(',')]
当然,这仅适用于本身不包含逗号或处理引号的值。为此,您应该采用更先进的技术。
编辑:如果您不介意额外的依赖,您可以查看ConfigObj,它本机支持列表作为值类型。