使用Python将ini文件中的所有内容读入字典

pro*_*eek 20 python ini configuration-files

通常,我按如下方式编码,以获取变量中的特定项目,如下所示

try:
    config = ConfigParser.ConfigParser()
    config.read(self.iniPathName)
except ConfigParser.MissingSectionHeaderError, e:
    raise WrongIniFormatError(`e`)

try:
    self.makeDB = config.get("DB","makeDB")
except ConfigParser.NoOptionError:
    self.makeDB = 0
Run Code Online (Sandbox Code Playgroud)

有没有办法读取python字典中的所有内容?

例如

[A]
x=1
y=2
z=3
[B]
x=1
y=2
z=3

被写入

val["A"]["x"] = 1
...
val["B"]["z"] = 3

Ale*_*lli 31

我建议子类化ConfigParser.ConfigParser(或SafeConfigParser,&c)安全地访问"受保护"属性(以单下划线开头的名称 - "private"将是以两个下划线开头的名称,即使在子类中也不能访问...):

import ConfigParser

class MyParser(ConfigParser.ConfigParser):

    def as_dict(self):
        d = dict(self._sections)
        for k in d:
            d[k] = dict(self._defaults, **d[k])
            d[k].pop('__name__', None)
        return d
Run Code Online (Sandbox Code Playgroud)

这模拟了配置解析器的通常逻辑,并保证在所有版本的Python中都有效,其中有一个ConfigParser.py模块(最多2.7个,这是该2.*系列的最后一个- 知道将来不会有Python 2.任何版本都是如何保证兼容性;-).

如果你需要支持未来的Python 3.*版本(最多3.1版本,可能是即将推出的3.2版本应该没问题,只需将模块重命名为全小写configparser而非当然),未来几年可能需要一些关注/调整,但是我不指望任何重大的东西.


pro*_*eek 27

我设法得到答案,但我希望应该有一个更好的答案.

dictionary = {}
for section in config.sections():
    dictionary[section] = {}
    for option in config.options(section):
        dictionary[section][option] = config.get(section, option)
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是一个非常好的解决方案,为什么你不满意呢? (2认同)
  • 这应该是答案,因为它解决了问题而无需使用"私有""_sections"属性.当然,如果需要使用OrderedDict,只需使用它代替常规字典. (2认同)

And*_*rew 10

ConfigParser的实例数据在内部存储为嵌套的dict.您可以复制它,而不是重新创建它.

>>> import ConfigParser
>>> p = ConfigParser.ConfigParser()
>>> p.read("sample_config.ini")
['sample_config.ini']
>>> p.__dict__
{'_defaults': {}, '_sections': {'A': {'y': '2', '__name__': 'A', 'z': '3', 'x': '1'}, 'B':         {'y': '2', '__name__': 'B', 'z': '3', 'x': '1'}}, '_dict': <type 'dict'>}
>>> d = p.__dict__['_sections'].copy()
>>> d
{'A': {'y': '2', '__name__': 'A', 'z': '3', 'x': '1'}, 'B': {'y': '2', '__name__': 'B', 'z': '3', 'x': '1'}}
Run Code Online (Sandbox Code Playgroud)

编辑:

Alex Martelli的解决方案更清洁,更强大,更漂亮.虽然这是公认的答案,但我建议改用他的方法.有关详细信息,请参阅他对此解决方案的评论

  • 我总是不愿意访问受保护的("起始下划线")属性名称(通过`__dict__`的荒谬并发症根本没有帮助 - `d = p._sections.copy()`完全等同,更简单,更直接).这就是为什么我在我的回答中建议使用子类的替代方法 - 子类是_expected_来访问基类的受保护属性.在C++中,这是强制执行的; 在Python中,它不是,但那是因为用户应该足够严格,不能_need_ enfor ;-). (5认同)

Evg*_*pin 10

我知道这个问题是5年前提出的,但是今天我已经把这个词汇理解得很好了:

parser = ConfigParser()
parser.read(filename)
confdict = {section: dict(parser.items(section)) for section in parser.sections()}
Run Code Online (Sandbox Code Playgroud)