我使用 ConfigParser 从配置文件加载数据,如下所示:
test.conf:
[myfiles]
fileone: %(datadir)s/somefile.foo
filetwo: %(datadir)s/nudderfile.foo
load.py:
import ConfigParser
config = ConfigParser.ConfigParser({'datadir': '/tmp'})
config.read('test.conf')
print config.items('myfiles')
print config.get('myfiles', 'datadir')
输出:
$ python load.py
[('datadir', '/tmp'), ('filetwo', '/tmp/nudderfile.foo'), ('fileone', '/tmp/somefile.foo')]
/tmp
我令人惊讶的是变量替换 ('datadir', '/tmp')
的默认值显示为 .items()
和 .get() 的一部分
返回,就像它们是配置文件中的值一样。这种行为是预期的吗?有什么解决方法,以便我可以简单地迭代 .items()
而不获取其中的默认字典值,但仍然使用魔术插值?
参考: http://docs.python.org/library/configparser.html
谢谢!
更新:有人指出这是预期的行为:默认值就像配置文件中的任何其他名称/值对一样。同样,配置文件中的名称/值对也可用于“神奇插值”,因此如果我定义:
foo: bar
zap: %(foo)snowl
我将得到 [... ('zap': 'barnowl')]
这非常简洁,但我仍然想知道是否可以完成我想要完成的任务:迭代配置文件中的名称/值对,使用变量插值,而不使用默认值。
我的具体场景是这样的:我想用 {basedir: '/foo/bar'}
之类的东西初始化配置对象,因为某些文件的绝对路径因安装而异。然后我需要将该配置对象传递给并让各种其他类迭代这些文件。我不希望每个读取配置的类都必须知道它是使用某些默认值初始化的,并且应该忽略它们,因为它们不是实际的文件。这可能吗?有什么方法可以隐藏 .item() 和 .get() 的默认值但仍然有插值?谢谢!
I'm using ConfigParser to load in data from a configuration file as follows:
test.conf:
[myfiles]
fileone: %(datadir)s/somefile.foo
filetwo: %(datadir)s/nudderfile.foo
load.py:
import ConfigParser
config = ConfigParser.ConfigParser({'datadir': '/tmp'})
config.read('test.conf')
print config.items('myfiles')
print config.get('myfiles', 'datadir')
Output:
$ python load.py
[('datadir', '/tmp'), ('filetwo', '/tmp/nudderfile.foo'), ('fileone', '/tmp/somefile.foo')]
/tmp
I'm surprised that the defaults for variable substitution ('datadir', '/tmp')
are showing up as part of the .items()
and .get()
returns, as if they were values in the configuration file. Is this behavior expected? Any work arounds, so that I can simply iterate .items()
without getting the default dictionary values in there, but still using the magic interpolation?
Reference: http://docs.python.org/library/configparser.html
Thanks!
Update: It's been pointed out that this is the expected behavior: defaults are just like any other name/value pair in the configuration file. Similarly, the name/value pairs in the configuration file are also available for "magic interpolation", so if I define:
foo: bar
zap: %(foo)snowl
I'll get [... ('zap': 'barnowl')]
That's pretty neat, but I'm still wondering if I can accomplish what I want to accomplish: iterate over the name/value pairs in my configuration files, with interpolation of variables, without the defaults.
My specific scenario is this: I wanted to initialize the config object with something like {basedir: '/foo/bar'}
, as the absolute paths to certain files varies by installation. Then I need to pass that config object around to and have various other classes iterate through the files. I don't want every class that reads the configuration to have to know that it was initialized with certain defaults and that it should ignore them, as they are not actual files. Is this possible? Any way to hide the defaults from .item() and .get() but still have interpolation? Thanks!
发布评论
评论(5)
一般来说,我发现 configparser.Configparser 类非常有帮助,但也有所欠缺。 其他人也有。
然而,它可以被子类化和扩展,有时很好,有时不太好(=非常依赖于实现)
这是您的问题的解决方案,在Python3中测试:
这是不好的例子之一,因为它正在部分复制
源代码 >选项()
。如果 configparser 基类RawConfigParser
能够提供一个包含异常转换的选项_options(self,section)
的内部 getter,以及一个options ,那就更好了()
会利用它。然后,在子类化中我们可以重用_options()
。对于 Python 2,我相信唯一的变化是对
super(ConfigParser,self)
的super()
调用。然后您可以使用:
并使用该列表进行迭代。
Generally, I've found the configparser.Configparser class very helpful, but also lacking. Others have, too.
However, it can be subclassed and extended, sometimes nicely, sometimes not so nicely (=very implementation dependent)
Here's a solution for your problem, tested in Python3:
This is one of the bad examples, because it is partially copying the source code of
options()
. It would be nicer if the configparser base classRawConfigParser
would provide an internal getter of options_options(self, section)
which would incorporate the exception cast, and aoptions()
which would make use of that. Then, in subclassing we could reuse the_options()
.For Python 2, I believe the only change is the
super()
call tosuper(ConfigParser,self)
.You can then use:
And also use that list to iterate.
为了回答这个问题,我注册了一个帐户。当我搜索时,它似乎是谷歌上的热门搜索。
我深入研究了
源代码 >ConfigParser
找到我认为简单而有效的解决方案。RawConfigParser
类(ConfigParser
继承)有一个名为default_section
的关键字参数。我能够通过实例化来忽略配置的 DEFAULT 部分:我希望这也可以帮助其他人。
更新
实际上,default_section应该是一个字符串,您可以自定义默认部分的名称“DEFAULT”。
因此,您可以:
I’ve made an account for the express purpose of answering this question. It seemed to be a top hit on Google when I was searching.
I dug into the source of
ConfigParser
to find what I think is a simple and efficient solution.There’s a keyword argument to the
RawConfigParser
class (whichConfigParser
inherits) calleddefault_section
. I was able to ignore the DEFAULT section of my config by instantiating with:I hope this can help someone else as well.
Update
Actually, the default_section should be a string and you can customize the name of the default section which is 'DEFAULT'.
So either you can:
你就不能过滤掉默认值吗?
例如:
filtered_items = [x for x in config.items('myfiles') if x[0] not in config.defaults()]
Can't you just filter out the defaults?
e.g.:
filtered_items = [x for x in config.items('myfiles') if x[0] not in config.defaults()]
试试这个:
blahblahblah
键也会出现在items
中,不是因为它是 .ini 文件中的模板,而是因为您将其指定为默认值。这就是 ConfigParser 处理默认值的方式:如果它在文件中找不到它们,它会分配它们的默认值。所以在我看来你在这里有一个简单的概念混淆。
Try this:
The
blahblahblah
key will also appear initems
, not because it's a template in the .ini file, but because you specified it as a default. This is how ConfigParser treats defaults: if it can't find them in the file, it assigns their default values.So it appears to me you have a simple confusion of concepts here.
以下内容应仅提供 myfiles 部分中的键/值对,而不会列出 DEFAULT 中的键/值对:
The following should give you only the key/value pairs in the myfiles section without also listing out those in DEFAULT: