Конвертировать ConfigParser.items('') в словарь

Как я могу преобразовать результат 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')

6 ответов

Решение

На самом деле это уже сделано для вас в config._sections, Пример:

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

[Second Section]
othervar = othervalue
otherkey = otheritem

А потом:

>>> 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'}

Изменить: Мое решение той же проблемы было отклонено, поэтому я дополнительно проиллюстрирую, как мой ответ делает то же самое, не пропуская раздел dict(), так как config._sections модуль уже для вас.

Пример test.ini:

[db]
dbname = testdb
dbuser = test_user
host   = localhost
password = abc123
port   = 3306

Волшебство происходит:

>>> 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'"

Таким образом, это решение не является неправильным, и на самом деле оно требует еще одного шага. Спасибо, что зашли!

Ты пытался

print connection_string % dict(config.items('db'))

?

Как я это сделал в одну строчку.

my_config_parser_dict = {s:dict(config.items(s)) for s in config.sections()}

Не больше, чем другие ответы, но когда дело не в реальных методах вашего метода, и вам нужно его просто в одном месте, используйте меньше строк и используйте силу понимания диктата, что может быть полезным.

Я знаю, что это было задано давно и выбрано решение, но выбранное решение не учитывает значения по умолчанию и подстановку переменных. Так как это первое попадание при поиске создания диктов из анализаторов, я решил опубликовать свое решение, которое включает в себя замены по умолчанию и замены переменных с помощью 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'}}

Удобная функция для этого может выглядеть примерно так:

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

Для отдельного раздела, например "общего", вы можете сделать:

dict(parser['general'])

В Python +3.6 вы могли это сделать

file.ini

[SECTION1]
one = 1
two = 2

[SECTION2]
foo = Hello
bar = World

[SECTION3]
param1 = parameter one
param2 = parameter two

file.py

import configparser

cfg = configparser.ConfigParser()
cfg.read('file.ini')
# Get one section in a dict
numbers = {k:v for k, v in cfg['SECTION1'].items()}

Если вам нужны все перечисленные разделы, вы должны использовать cfg.sections()

Другой альтернативой может быть:

config.ini

[DEFAULT]
potato=3

[foo]
foor_property=y
potato=4


[bar]
bar_property=y

parser.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()}

main.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()

Комбинируя ответ Микеле д'Амико и Кайла (без диктата), получается менее читаемый, но в какой-то мере убедительный:

{i: {i[0]: i[1] for i in config.items(i)} for i in config.sections()}

Вот еще один подход с использованием Python 3.7 с configparser а также ast.literal_eval:

game.ini

[assets]
tileset = {0:(32, 446, 48, 48), 
           1:(96, 446, 16, 48)}

game.py

import configparser
from ast import literal_eval

config = configparser.ConfigParser()
config.read('game.ini')

# convert a string to dict
tileset = literal_eval(config['assets']['tileset'])

print('tileset:', tileset)
print('type(tileset):', type(tileset))

выход

tileset: {0: (32, 446, 48, 48), 1: (96, 446, 16, 48)}
type(tileset): <class 'dict'>
Другие вопросы по тегам