Python 的 ConfigParser 每个部分的唯一键

发布于 2024-07-09 01:23:13 字数 1205 浏览 8 评论 0原文

我阅读了 文档 的部分,并看到 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 的实现发生更改,这可能会中断)?

我觉得这可能是那些“呃”时刻之一,我只看到了困难的解决方案。

[编辑:] 这是我如何多次使用同一个键的更精确示例:

[Ignored Paths]
ignore-extension: .swp
ignore-filename: tags
ignore-directory: bin

我不喜欢逗号分隔列表语法,因为当您将其缩放到许多价值观; 例如,由五十个扩展名组成的逗号分隔列表的可读性不是特别好。

I read the part of the docs and saw that the ConfigParser returns a list of key/value pairs for the options within a section. I figured that keys did not need to be unique within a section, otherwise the parser would just return a mapping. I designed my config file schema around this assumption, then sadly realized that this is not the case:

>>> 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')]

Then I went back and found the part of the docs that I should have read:

Sections are normally stored in a
builtin dictionary. An alternative
dictionary type can be passed to the
ConfigParser constructor. For example,
if a dictionary type is passed that
sorts its keys, the sections will be
sorted on write-back, as will be the
keys within each section.

To keep my existing configuration file scheme (which I really like now ;) I'm thinking of passing a mapping-like object as mentioned above that accumulates values instead of clobbering them. Is there a simpler way to prevent key/value collapse that I'm missing? Instead of making a crazy adapter (that could break if ConfigParser's implementation changes) should I just write a variant of the ConfigParser itself?

I feel like this may be one of those 'duh' moments where I'm only seeing the difficult solutions.

[Edit:] Here's a more precise example of how I'd like to use the same key multiple times:

[Ignored Paths]
ignore-extension: .swp
ignore-filename: tags
ignore-directory: bin

I dislike the comma-delimited-list syntax because it's hard on the eyes when you scale it to many values; for example, a comma delimited list of fifty extensions would not be particularly readable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

﹏雨一样淡蓝的深情 2024-07-16 01:23:13

ConfigParser 并不是为处理此类情况而设计的。 此外,你的配置文件对我来说没有意义。

ConfigParser 为每个部分提供了一个类似字典的结构,因此当您调用 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(',')]

当然,这仅适用于本身不包含逗号或不处理引用的值。 为此,您应该采用更高级的技术(请参阅这个这个< /a>)。

编辑:如果您不介意额外的依赖项,您可以查看 ConfigObj,它本身支持列表作为值类型。

ConfigParser isn't designed to handle such conditions. Furthermore, your config file doesn't make sense to me.

ConfigParser gives you a dict-like structure for each section, so when you call parser.items(section), I'm expecting similar output to dict.items(), which is just a list of key/value tuples. I would never expect to see something like:

[('spam', 'eggs'), ('spam', 'ham')]

Not to mention, how would you expect the following to behave?:

parser.get('Some Section', 'spam')

Which is the intended way to retrieve values.

If you want to store multiple values for the same key, I would suggest something like this in your config file:

[Some Section]
spam: eggs, ham

And this in your code:

spam_values = [v.strip() for v in parser.get('Some Section', 'spam').split(',')]

Of course, this will only work for values that don't contain commas themselves or handle quoting. For that, you should employ a more advanced technique (see this and this).

EDIT: If you don't mind the extra dependency, You could check out ConfigObj, which natively supports lists as a value type.

眼中杀气 2024-07-16 01:23:13

ConfigParser 的这种缺陷是 pyglet 使用 epydoc 的修补版本,用此 简单格式:

name: pyglet
url: http://www.pyglet.org/

output: html
target: doc/api/
...    
module: pyglet

exclude: pyglet.gl.gl
exclude: pyglet.gl.agl
exclude: pyglet.gl.lib_agl
exclude: pyglet.gl.wgl
...

如果您不需要部分 - 这种方法可以有用的。

This deficiency of ConfigParser is the reason why pyglet used patched version of epydoc to replace ConfigParser ini with this simple format:

name: pyglet
url: http://www.pyglet.org/

output: html
target: doc/api/
...    
module: pyglet

exclude: pyglet.gl.gl
exclude: pyglet.gl.agl
exclude: pyglet.gl.lib_agl
exclude: pyglet.gl.wgl
...

If you don't need sections - this approach can be useful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文