将ConfigParser.items('')转换为字典

Szy*_*ski 61 python

如何将ConfigParser.items('section')的结果转换为字典以格式化字符串,如下所示:

import ConfigParser

config = ConfigParser.ConfigParser()
config.read('conf.ini')

connection_string = ("dbname='%(dbname)s' user='%(dbuser)s' host='%(host)s' "
                     "password='%(password)s' port='%(port)s'")

print connection_string % config.items('db')
Run Code Online (Sandbox Code Playgroud)

Ian*_*and 93

你有没有尝试过

print connection_string % dict(config.items('db'))
Run Code Online (Sandbox Code Playgroud)

  • @Ricky,我想用户不应该访问_sections. (9认同)

jat*_*ism 51

这实际上已经为你完成了config._sections.例:

$ cat test.ini
[First Section]
var = value
key = item

[Second Section]
othervar = othervalue
otherkey = otheritem
Run Code Online (Sandbox Code Playgroud)

然后:

>>> from ConfigParser import ConfigParser
>>> config = ConfigParser()
>>> config.read('test.ini')
>>> config._sections
{'First Section': {'var': 'value', '__name__': 'First Section', 'key': 'item'}, 'Second Section': {'__name__': 'Second Section', 'otherkey': 'otheritem', 'othervar': 'othervalue'}}
>>> config._sections['First Section']
{'var': 'value', '__name__': 'First Section', 'key': 'item'}
Run Code Online (Sandbox Code Playgroud)

编辑: 我的解决方案相同的问题downvoted所以我会进一步说明我的答案是如何做同样的事情,而不必直通部分dict(),因为config._sections由模块为您已经提供.

示例test.ini:

[db]
dbname = testdb
dbuser = test_user
host   = localhost
password = abc123
port   = 3306
Run Code Online (Sandbox Code Playgroud)

魔术发生:

>>> config.read('test.ini')
['test.ini']
>>> config._sections
{'db': {'dbname': 'testdb', 'host': 'localhost', 'dbuser': 'test_user', '__name__': 'db', 'password': 'abc123', 'port': '3306'}}
>>> connection_string = "dbname='%(dbname)s' user='%(dbuser)s' host='%(host)s' password='%(password)s' port='%(port)s'"
>>> connection_string % config._sections['db']
"dbname='testdb' user='test_user' host='localhost' password='abc123' port='3306'"
Run Code Online (Sandbox Code Playgroud)

所以这个解决方案没有错,实际上只需要少一步.谢谢你的到来!

  • 使用_sections很危险.未在API中公开,不是未来的证明. (51认同)
  • 这是一个私人API和可怕的建议. (28认同)
  • 任何遵循这个建议的人都会让ConfigParser的维护人员变得更加艰难,如果他们决定改变内部工作的方式,那么人们建议使用私有API会让我很难过 (5认同)
  • 每个人都冷静下来.已经六年了,API尚未改变.现在,如果公共API实际改进并且更加用户友好,我将更新此答案. (5认同)
  • 我并不是说这是错的,但是我不能使用它,因为我用配置解析器的内置替换%(语法)来测试它.为了不知道这允许在其他配置值中使用配置值.它们不会在_sections成员中展开,而是通过items()函数展开. (3认同)
  • @jathanism 当人们按照您的建议误用 `_sections` 时,公共 API 更难改进。 (3认同)
  • 这是错误的方法,因为它不考虑默认值并且变量没有内插。 (2认同)
  • @jathanism的答案是正确的,当且仅当您不需要`ConfigParser`提供的默认和插值行为时。换句话说,当使用* raw *选项时,该答案等同于ConfigParser。并且不等同于非原始选项。后续注释(“发生了魔术”)显示了如何解决插值问题,而不是默认问题。底线:且仅当配置文件具有每个指定值的平面/最终版本时,config._sections才能正常工作;否则没有。 (2认同)
  • 重点是您不应该在模块本身之外访问这些内容。它就像私有变量。 (2认同)

Mic*_*ico 48

我是如何在一行中完成的.

my_config_parser_dict = {s:dict(config.items(s)) for s in config.sections()}
Run Code Online (Sandbox Code Playgroud)

仅仅是其他答案,但当它不是你的方法的真正业务,你只需要在一个地方使用更少的行,并采取dict理解的力量可能是有用的.

  • 优雅便携。 (4认同)
  • 这确实应该是公认的答案。这提供了一个非常Pythonic的解决方案,无需访问私有属性。 (2认同)

Jam*_*yle 15

我知道这是很久以前问的,并且选择了一个解决方案,但所选的解决方案没有考虑默认值和变量替换.因为它是搜索从解析器创建dicts时的第一个命中,我想我会发布我的解决方案,其中包含使用ConfigParser.items()的默认和可变替换.

from ConfigParser import SafeConfigParser
defaults = {'kone': 'oneval', 'ktwo': 'twoval'}
parser = SafeConfigParser(defaults=defaults)
parser.set('section1', 'kone', 'new-val-one')
parser.add_section('section1')
parser.set('section1', 'kone', 'new-val-one')
parser.get('section1', 'ktwo')
parser.add_section('section2')
parser.get('section2', 'kone')
parser.set('section2', 'kthree', 'threeval')
parser.items('section2')
thedict = {}
for section in parser.sections():
    thedict[section] = {}
    for key, val in parser.items(section):
        thedict[section][key] = val
thedict
{'section2': {'ktwo': 'twoval', 'kthree': 'threeval', 'kone': 'oneval'}, 'section1': {'ktwo': 'twoval', 'kone': 'new-val-one'}}
Run Code Online (Sandbox Code Playgroud)

执行此操作的便利功能可能如下所示:

def as_dict(config):
    """
    Converts a ConfigParser object into a dictionary.

    The resulting dictionary has sections as keys which point to a dict of the
    sections options as key => value pairs.
    """
    the_dict = {}
    for section in config.sections():
        the_dict[section] = {}
        for key, val in config.items(section):
            the_dict[section][key] = val
    return the_dict
Run Code Online (Sandbox Code Playgroud)


Kei*_*itt 8

对于单个部分,例如“一般”,您可以执行以下操作:

dict(parser['general'])
Run Code Online (Sandbox Code Playgroud)


cri*_*nru 7

在 Python +3.6 中你可以这样做

文件.ini

[SECTION1]
one = 1
two = 2

[SECTION2]
foo = Hello
bar = World

[SECTION3]
param1 = parameter one
param2 = parameter two
Run Code Online (Sandbox Code Playgroud)

文件.py

[SECTION1]
one = 1
two = 2

[SECTION2]
foo = Hello
bar = World

[SECTION3]
param1 = parameter one
param2 = parameter two
Run Code Online (Sandbox Code Playgroud)

如果您需要列出的所有部分,您应该使用cfg.sections()


小智 6

另一种选择是:

配置文件

[DEFAULT]
potato=3

[foo]
foor_property=y
potato=4


[bar]
bar_property=y
Run Code Online (Sandbox Code Playgroud)

解析器.py

import configparser
from typing import Dict


def to_dict(config: configparser.ConfigParser) -> Dict[str, Dict[str, str]]:
    """
    function converts a ConfigParser structure into a nested dict
    Each section name is a first level key in the the dict, and the key values of the section
    becomes the dict in the second level
    {
        'section_name': {
            'key': 'value'
        }
    }
    :param config:  the ConfigParser with the file already loaded
    :return: a nested dict
    """
    return {section_name: dict(config[section_name]) for section_name in config.sections()}
Run Code Online (Sandbox Code Playgroud)

主要.py

import configparser

from parser import to_dict


def main():
    config = configparser.ConfigParser()
    # By default section names are parsed to lower case, optionxform = str sets to no conversion.
    # For more information: https://docs.python.org/3/library/configparser.html#configparser-objects
    # config.optionxform = str
    config.read('config.ini')
    print(f'Config read: {to_dict(config)}')
    print(f'Defaults read: {config.defaults()}')


if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)