Convert ConfigParser.items('') to dictionary

Question:

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')
Asked By: Szymon Lipiński

||

Answers:

Have you tried

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

?

Answered By: Ian Clelland

This is actually already done for you in config._sections. Example:

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

[Second Section]
othervar = othervalue
otherkey = otheritem

And then:

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

Edit: My solution to the same problem was downvoted so I’ll further illustrate how my answer does the same thing without having to pass the section thru dict(), because config._sections is provided by the module for you already.

Example test.ini:

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

Magic happening:

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

So this solution is not wrong, and it actually requires one less step. Thanks for stopping by!

Answered By: jathanism

I know this was asked a long time ago and a solution chosen, but the solution selected does not take into account defaults and variable substitution. Since it’s the first hit when searching for creating dicts from parsers, thought I’d post my solution which does include default and variable substitutions by using 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'}}

A convenience function to do this might look something like:

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
Answered By: James Kyle

For an individual section, e.g. “general”, you can do:

dict(parser['general'])
Answered By: Keith Hughitt

How I did it in just one line.

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

No more than other answers but when it is not the real businesses of your method and you need it just in one place use less lines and take the power of dict comprehension could be useful.

Answered By: Michele d'Amico

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'>
Answered By: rbento

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()}
Answered By: fzzylogic

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

Answered By: crisconru

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()
Answered By: Dinesh Trivedi
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.