2010-02-03 46 views
11

我使用ConfigParser在从配置文件数据来加载如下:如何从Python ConfigParser .items()中排除DEFAULT?

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()的默认值,但仍然有插值?谢谢!

+2

我不能完全理解为什么这是默认的行为,更不用说为什么没有办法将其关闭。 – 2014-12-22 16:33:52

回答

1

试试这个:

config = ConfigParser.ConfigParser({'blahblahblah': 'blah'}) 
config.read('test.conf') 

blahblahblah键也将出现在items,不是因为它是在.ini文件的模板,而是因为你指定它作为默认。这是ConfigParser如何处理默认值:如果它在文件中找不到它们,它将分配它们的默认值。

因此,在我看来你在这里有一个简单的概念混淆。

+0

感谢您的澄清。因此默认字典用于*既提供某些键的默认值,也提供嵌入在配置文件中的变量的“魔术插值”。 此外,在配置文件中定义的变量也用于 “神奇插值”,所以如果我定义: FOO:酒吧 ZAP:%(富)snowl 我会[...('ZAP “:‘barnowl’)] 这是相当整洁,但我一直在想,如果我能做到我想要完成的任务:在名称/值对迭代在我的配置文件,与变量插值,没有默认值。 – user264902 2010-02-03 04:36:16

4

一般来说,我发现configparser.Configparser类非常有帮助,但也缺乏。 Others have, too

然而,可以被继承和扩展,有时很好,有时不那么好听(=非常依赖于实现)

这里是你的问题的解决方案,在Python3测试:

class ConfigParser(configparser.ConfigParser): 
    """Can get options() without defaults 
    """ 
    def options(self, section, no_defaults=False, **kwargs): 
     if no_defaults: 
      try: 
       return list(self._sections[section].keys()) 
      except KeyError: 
       raise NoSectionError(section) 
     else: 
      return super().options(section, **kwargs) 

这是坏的例子之一,因为它是部分复制的options()the source code。这将是更好,如果configparser基类RawConfigParser将提供的选项_options(self, section)内部的吸气将纳入例外投和options()这将充分利用这一点。然后,在子类中,我们可以重新使用_options()

对于Python 2,我相信唯一的变化是super()调用super(ConfigParser,self)

然后,您可以使用:

print config.options('myfiles', no_defaults=True) 

,还可以使用该列表进行迭代。

+0

你在正确的轨道上,但他被问及.items(),没有可供选项()。不过,我认为这会让他在那里。 – 2013-01-11 09:53:05

+0

我明白他的问题是如何“遍历在我的配置文件中的名称/值对,用变量插值,没有默认值。”这就是上面的代码所做的。对我来说,这是一个确切的答案。不幸的是,情况经常是这样,问题的海报似乎并不活跃。否则,我们可以让他决定是否可以接受答案。 – cfi 2013-01-11 12:02:17

+0

是的,这个问题依然存在,需要关注。他在代码中使用了.items,在最后一句中使用了.item。他要求名称/值对,这是.items所做的。选项只是返回键。你的回答帮助我覆盖.items,尽管如此谢谢。 – 2013-01-12 05:03:43

2

你就不能过滤掉的默认值?

例如为:

filtered_items = [x for x in config.items('myfiles') if x[0] not in config.defaults()]