Convert ConfigParser.items('') to dictionary

Viewed 102620

How can I convert the result of a ConfigParser.items('section') to a dictionary to format a string like here:

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')
9 Answers

Another alternative would be:

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

In Python +3.6 you could do this

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

If you need all sections listed you should use cfg.sections()

Combining Michele d'Amico and Kyle's answer (no dict), produces a less readable but somehow compelling:

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

Here is another approach using Python 3.7 with configparser and 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))

output

tileset: {0: (32, 446, 48, 48), 1: (96, 446, 16, 48)}
type(tileset): <class 'dict'>
Related