如何从Python ConfigParser .items()中排除DEFAULT?

use*_*902 15 python configuration configparser defaults

我正在使用ConfigParser从配置文件加载数据,如下所示:

test.conf:

[myfiles]
fileone: %(datadir)s/somefile.foo
filetwo: %(datadir)s/nudderfile.foo
Run Code Online (Sandbox Code Playgroud)

load.py:

import ConfigParser

config = ConfigParser.ConfigParser({'datadir': '/tmp'})
config.read('test.conf')

print config.items('myfiles')
print config.get('myfiles', 'datadir')
Run Code Online (Sandbox Code Playgroud)

输出:

$ python load.py 
[('datadir', '/tmp'), ('filetwo', '/tmp/nudderfile.foo'), ('fileone', '/tmp/somefile.foo')]
/tmp
Run Code Online (Sandbox Code Playgroud)

我很惊讶变量替换的默认值('datadir', '/tmp')是作为一部分出现的.items().get()返回,就像它们是配置文件中的值一样.这种行为有望吗?任何解决方法,以便我可以简单地迭代.items()而不获取那里的默认字典值,但仍然使用魔术插值?

参考:http://docs.python.org/library/configparser.html

谢谢!

更新:已经指出这是预期的行为:默认值与配置文件中的任何其他名称/值对一样.同样,配置文件中的名称/值对也可用于"魔术插值",所以如果我定义:

foo: bar
zap: %(foo)snowl
Run Code Online (Sandbox Code Playgroud)

我去拿 [... ('zap': 'barnowl')]

这非常简洁,但我仍然想知道我是否能完成我想要完成的任务:迭代我的配置文件中的名称/值对,插入变量,没有默认值.

我的具体情况是:我想用类似的东西初始化配置对象{basedir: '/foo/bar'},因为某些文件的绝对路径因安装而异.然后我需要传递该配置对象并让各种其他类遍历文件.我不希望每个读取配置的类都必须知道它是使用某些默认值初始化的,并且它应该忽略它们,因为它们不是实际文件.这可能吗?有什么方法可以隐藏.item()和.get()的默认值但仍有插值?谢谢!

cfi*_*cfi 8

一般来说,我发现configparser.Configparser类非常有用,但也缺乏.其他人也有.

但是,它可以被子类化和扩展,有时很好,有时候不太好(=非常依赖于实现)

这是针对您的问题的解决方案,在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)
Run Code Online (Sandbox Code Playgroud)

这是不好的例子之一,因为它被部分复制的源代码options().如果configparser基类RawConfigParser提供一个内部的getter选项_options(self, section),它将包含异常转换,并且options()可以使用它,那就更好了.然后,在子类中我们可以重用_options().

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

然后你可以使用:

print config.options('myfiles', no_defaults=True)
Run Code Online (Sandbox Code Playgroud)

并且还使用该列表进行迭代.


小智 6

我\xe2\x80\x99为了回答这个问题而注册了一个帐户。当我搜索时,它似乎是谷歌上的热门搜索。

\n

我深入研究了源头ConfigParser,找到了我认为简单而有效的解决方案。

\n

RawConfigParser\xe2\x80\x99s类(ConfigParser继承)有一个关键字参数,称为default_section。我可以通过实例化来忽略配置的 DEFAULT 部分:

\n
from configparser import ConfigParser\n\nparser = ConfigParser(default_section=None)\n
Run Code Online (Sandbox Code Playgroud)\n

我希望这也可以帮助其他人。

\n


mhr*_*che 5

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

例如:

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


Eli*_*sky 1

尝试这个:

config = ConfigParser.ConfigParser({'blahblahblah': 'blah'})
config.read('test.conf')
Run Code Online (Sandbox Code Playgroud)

blahblahblah密钥也会出现在 中items,不是因为它是 .ini 文件中的模板,而是因为您将其指定为默认值。这就是 ConfigParser 处理默认值的方式:如果它在文件中找不到它们,它会分配它们的默认值。

所以在我看来你在这里有一个简单的概念混淆。