简体   繁体   中英

using ConfigParser and dictionary in Python

I am trying some basic python scripts using ConfigParser and converting to a dictionary. I am reading a file named "file.cfg" which contains three sections - root, first, second. Currently the code reads the file and converts everything within the file to a dictionary.

My requirement is to convert only sections named "first" and "second" and so on, its key value pair to a dictionary. What would be best way of excluding the section "root" and its key value pair?

import urllib
import urllib2
import base64
import json
import sys
from ConfigParser import SafeConfigParser

parser = SafeConfigParser()
parser.read('file.cfg')

print parser.get('root', 'auth')

config_dict = {}

for sect in parser.sections():
    config_dict[sect] = {}
    for name, value in parser.items(sect):
        config_dict[sect][name] = value

print config_dict

Contents of file.cfg -

~]# cat file.cfg

[root]
username = admin
password = admin
auth = http://192.168.1.1/login

[first]
username = pete
password = sEcReT
url = http://192.168.1.1/list

[second]
username = ron
password = SeCrET
url = http://192.168.1.1/status

Output of the script -

 ~]# python test4.py 

http://192.168.1.1/login
{'second': {'username': 'ron', 'url': 'http://192.168.1.1/status', 'password': 'SeCrEt'}, 'root': {'username': 'admin', 'password': 'admin', 'auth': 'http://192.168.1.1/login'}, 'first': {'username': 'pete', 'url': 'http://192.168.1.1/list', 'password': 'sEcReT'}}

You can remove root section from parser.sections() as follows:

parser.remove_section('root')

Also you don't have to iterate over each pair in each section. You can just convert them to dict :

config_dict = {}
for sect in parser.sections():
    config_dict[sect] = dict(parser.items(sect))

Here is one liner:

config_dict = {sect: dict(parser.items(sect)) for sect in parser.sections()}

Bypass the root section by comparison.

for sect in parser.sections():
    if sect == 'root':
        continue
    config_dict[sect] = {}
    for name, value in parser.items(sect):
        config_dict[sect][name] = value

Edit after acceptance:

ozgur's one liner is a much more concise solution. Upvote from me. If you don't feel like removing sections from the parser directly, the entry can be deleted afterwards.

config_dict = {sect: dict(parser.items(sect)) for sect in parser.sections()} # ozgur's one-liner
del config_dict['root']

Maybe a bit off topic, but ConfigParser is a real pain when in comes to store int, floats and booleans. I prefer using dicts which I dump into configparser.

I also use funtcions to convert between ConfigParser objects and dicts, but those deal with variable type changing, so ConfigParser is happy since it requests strings, and my program is happy since 'False' is not False.

def configparser_to_dict(config: configparser.ConfigParser) -> dict:
    config_dict = {}
    for section in config.sections():
        config_dict[section] = {}
        for key, value in config.items(section):
            # Now try to convert back to original types if possible
            for boolean in ['True', 'False', 'None']:
                if value == boolean:
                    value = bool(boolean)

            # Try to convert to float or int
            try:
                if isinstance(value, str):
                    if '.' in value:
                        value = float(value)
                    else:
                        value = int(value)
            except ValueError:
                pass

            config_dict[section][key] = value

    # Now drop root section if present
    config_dict.pop('root', None)
    return config_dict


def dict_to_configparser(config_dict: dict) -> configparser.ConfigParser:
    config = configparser.ConfigParser()

    for section in config_dict.keys():
        config.add_section(section)
        # Now let's convert all objects to strings so configparser is happy
        for key, value in config_dict[section].items():
            config[section][key] = str(value)

    return config

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM