views:

115

answers:

3

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
+2  A: 

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
I think this is a very good solution, why aren't you happy with it?
Tim Pietzcker
+2  A: 

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.

Andrew
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
+2  A: 

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