Read all the contents in ini file into dictionary with Python
Asked Answered
O

8

34

Normally, I code as follows for getting a particular item in a variable as follows

try:
    config = ConfigParser.ConfigParser()
    config.read(self.iniPathName)
except ConfigParser.MissingSectionHeaderError, e:
    raise WrongIniFormatError(`e`)

try:
    self.makeDB = config.get("DB","makeDB")
except ConfigParser.NoOptionError:
    self.makeDB = 0

Is there any way to read all the contents in a python dictionary?

For example

[A]
x=1
y=2
z=3
[B]
x=1
y=2
z=3

is written into

val["A"]["x"] = 1
...
val["B"]["z"] = 3
Octan answered 10/7, 2010 at 20:6 Comment(1)
ConfigParser from Python 3 has this functionality, and you may use the backport to have it in Python 2Excerpta
H
44

I suggest subclassing ConfigParser.ConfigParser (or SafeConfigParser, &c) to safely access the "protected" attributes (names starting with single underscore -- "private" would be names starting with two underscores, not to be accessed even in subclasses...):

import ConfigParser

class MyParser(ConfigParser.ConfigParser):

    def as_dict(self):
        d = dict(self._sections)
        for k in d:
            d[k] = dict(self._defaults, **d[k])
            d[k].pop('__name__', None)
        return d

This emulates the usual logic of config parsers, and is guaranteed to work in all versions of Python where there's a ConfigParser.py module (up to 2.7, which is the last of the 2.* series -- knowing that there will be no future Python 2.any versions is how compatibility can be guaranteed;-).

If you need to support future Python 3.* versions (up to 3.1 and probably the soon forthcoming 3.2 it should be fine, just renaming the module to all-lowercase configparser instead of course) it may need some attention/tweaks a few years down the road, but I wouldn't expect anything major.

Haematothermal answered 10/7, 2010 at 21:26 Comment(2)
Tried your answer and the keys are all lowercased. e.g. for: """ [title] KEY1 = VAL1 """" I get in config['title']: {key1: VAL1} This is because the dictionary inside self_sections has lowercase keys in the first place so it appears... see #19360056Buckler
Seems like adding this to your class constructor solves the lowercase issue: def __init__(self): super().__init__() self.optionxform = strBuckler
O
36

I managed to get an answer, but I expect there should be a better one.

dictionary = {}
for section in config.sections():
    dictionary[section] = {}
    for option in config.options(section):
        dictionary[section][option] = config.get(section, option)
Octan answered 10/7, 2010 at 20:31 Comment(3)
I think this is a very good solution, why aren't you happy with it?Ho
This should be the answer because it solves the problem without having to use the "private" "_sections" attribute. And, of course, if one needs to use an OrderedDict, just use that in place of the regular dict.Priming
Replacing dictionary with a defaultdict(dict) would remove the intermediate dict creation.Kironde
Q
24

I know that this question was asked 5 years ago, but today I've made this dict comprehension thingy:

parser = ConfigParser()
parser.read(filename)
confdict = {section: dict(parser.items(section)) for section in parser.sections()}
Quita answered 11/4, 2016 at 11:30 Comment(0)
P
12

The instance data for ConfigParser is stored internally as a nested dict. Instead of recreating it, you could just copy it.

>>> import ConfigParser
>>> p = ConfigParser.ConfigParser()
>>> p.read("sample_config.ini")
['sample_config.ini']
>>> p.__dict__
{'_defaults': {}, '_sections': {'A': {'y': '2', '__name__': 'A', 'z': '3', 'x': '1'}, 'B':         {'y': '2', '__name__': 'B', 'z': '3', 'x': '1'}}, '_dict': <type 'dict'>}
>>> d = p.__dict__['_sections'].copy()
>>> d
{'A': {'y': '2', '__name__': 'A', 'z': '3', 'x': '1'}, 'B': {'y': '2', '__name__': 'B', 'z': '3', 'x': '1'}}

Edit:

Alex Martelli's solution is cleaner, more robust, and prettier. While this was the accepted answer, I'd suggest using his approach instead. See his comment to this solution for more info.

Partial answered 10/7, 2010 at 21:24 Comment(1)
I'm always loath of accessing protected ("start-with-underscore") names of attributes (and the absurd complication of going through __dict__ doesn't help at all -- d=p._sections.copy() is exactly equivalent, simpler, and more direct). That's why I suggested in my answer the alternative of using a subclass instead -- subclasses are expected to access protected attributes of the base class. In C++ this is enforced; in Python, it isn't, but that's because users are supposed to be disciplined enough to not need enforcement;-).Haematothermal
A
2

How to parse ini file in py?

import ConfigParser
config = ConfigParser.ConfigParser()
config.read('/var/tmp/test.ini')
print config.get('DEFAULT', 'network')

Where test.ini file contain:

[DEFAULT]
network=shutup
others=talk
Abiding answered 9/12, 2012 at 8:44 Comment(0)
S
1

One more thing to take care is, ConfigParser converts the key values to lowercase hence in case you are converting the config entries to a dictionary cross check your requirements. I faced a problem because of this. For me I was having camel-case keys hence, had to change some amount of code when I started using the dictionary instead of files. ConfigParser.get() method internally converts the key to lower-case.

Slingshot answered 30/9, 2016 at 12:37 Comment(0)
D
0

suppose file: config.properties contains the following:

  • k =v
  • k2= v2
  • k3= v3

python code:

def read_config_file(file_path):
        with open(file=file_path, mode='r') as fs:
            return {k.strip(): v.strip() for i in [l for l in fs.readlines() if l.strip() != ''] for k, v in [i.split('=')]}


print('file as dic: ', read_config_file('config.properties'))
Dispassionate answered 19/5, 2019 at 4:56 Comment(0)
D
-1

from https://wiki.python.org/moin/ConfigParserExamples

def ConfigSectionMap(section):
dict1 = {}
options = Config.options(section)
for option in options:
    try:
        dict1[option] = Config.get(section, option)
        if dict1[option] == -1:
            DebugPrint("skip: %s" % option)
    except:
        print("exception on %s!" % option)
        dict1[option] = None
return dict1
Dollydolman answered 1/2, 2017 at 14:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.