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
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
prosseek
  • 182,215
  • 215
  • 566
  • 871
  • ConfigParser from Python 3 has this functionality, and you may use the [backport](https://pypi.org/project/configparser/) to have it in Python 2 – bartolo-otrit Jan 14 '19 at 12:22

8 Answers8

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.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 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 https://stackoverflow.com/questions/19359556/configparser-reads-capital-keys-and-make-them-lower-case – Or b Jan 18 '22 at 17:28
  • Seems like adding this to your class constructor solves the lowercase issue: `def __init__(self): super().__init__() self.optionxform = str` – Or b Jan 18 '22 at 17:41
35

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)
prosseek
  • 182,215
  • 215
  • 566
  • 871
  • 2
    I think this is a very good solution, why aren't you happy with it? – Tim Pietzcker Jul 10 '10 at 20:52
  • 2
    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. – SizzlingVortex Oct 14 '15 at 16:25
  • 1
    Replacing `dictionary` with a `defaultdict(dict)` would remove the intermediate dict creation. – noxdafox Mar 03 '16 at 11:29
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()}
Evgeny Sharypin
  • 649
  • 6
  • 7
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.

Community
  • 1
  • 1
Andrew
  • 12,821
  • 2
  • 26
  • 18
  • 5
    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;-). – Alex Martelli Jul 11 '10 at 00:14
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
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.

Ali Bdeir
  • 4,151
  • 10
  • 57
  • 117
avitash
  • 19
  • 3
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'))
Mohamed.Abdo
  • 2,054
  • 1
  • 19
  • 12
-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
Dvir Arad
  • 147
  • 1
  • 9