How to parse configuration files in Python

There are several solutions to parse configuration files in Python.

These are usually text files contain a list of options with a name and a value, such as "port=8080" or "user: admin". More elaborate configuration files such as "INI files" on Windows contain sections to organize options. A section starts with a name between square brackets, such as "[section1]".

ConfigParser for INI files with sections

See http://docs.python.org/library/configparser.html

This parser is powerful, but it does not support simple configuration files without sections.

SimpleConfigParser for config files without sections

As Fredrik Lundh proposed on the python-dev mailing-list, it is quite simple to extend ConfigParser to support files without sections: http://mail.python.org/pipermail/python-dev/2002-November/029987.html

I have made a module called SimpleConfigParser based on that idea, that you can reuse in your own projects. See attached file below.

Sample usage:

import SimpleConfigParser
filename = 'sample_config_no_section.ini'
cp = SimpleConfigParser.SimpleConfigParser()
cp.read(filename)
print 'getoptionslist():', cp.getoptionslist()
for option in cp.getoptionslist():
    print "getoption('%s') = '%s'" % (option, cp.getoption(option))
print "hasoption('wrongname') =", cp.hasoption('wrongname')

 

ConfigObj for more advanced config files

ConfigObj is able to handle INI config files with sections and subsections, among other enhancements.

see http://www.voidspace.org.uk/python/configobj.html

ElementTree for XML config files

see http://www.decalage.info/en/python/etree

Custom config file parser

In fact it is very easy to create your own configuration file parser, thanks to Python string methods such as split() and strip(). For example the following function is able to parse simple configurations files and return a dictionary of parameters:

COMMENT_CHAR = '#'
OPTION_CHAR =  '='
 
def parse_config(filename):
    options = {}
    f = open(filename)
    for line in f:
        # First, remove comments:
        if COMMENT_CHAR in line:
            # split on comment char, keep only the part before
            line, comment = line.split(COMMENT_CHAR, 1)
        # Second, find lines with an option=value:
        if OPTION_CHAR in line:
            # split on option char:
            option, value = line.split(OPTION_CHAR, 1)
            # strip spaces:
            option = option.strip()
            value = value.strip()
            # store in dictionary:
            options[option] = value
    f.close()
    return options
 
options = parse_config('config.ini')
print options

 


 

AttachmentSize
SimpleConfigParser-0.02.zip2.01 KB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Improved custom config parser

Hi, here is a code of my ini files parser in python.
I made it so it can accept comment that starts with '#' or ';' and they end on the line break so can start after the section or key-value pairs.

#comment1
;comment2

The key-value separator can be '=' or ':' and the whitespaces can be arbitrary.
key1: value1
key2 = value2

There can be key-value pairs before the first section, they are stored in the 'global' section then.
And the sections can be nested with dot separation.
[section.subsection.subsubsection]

Here is the code:

  1. class ParseINI(dict):
  2. def __init__(self, f):
  3. self.f = f
  4. self.__read()
  5.  
  6. def __read(self):
  7. with open(self.f, 'r') as f:
  8. slovnik = self
  9. for line in f:
  10. if not line.startswith("#") and not line.startswith(';') and line.strip() != "":
  11. line = line.replace('=', ':')
  12. line = line.replace(';', '#')
  13. index = line.find('#')
  14. line = line[:index]
  15. line = line.strip()
  16. if line.startswith("["):
  17. sections = line[1:-1].split('.')
  18. slovnik = self
  19. for section in sections:
  20. if section not in slovnik:
  21. slovnik[section] = {}
  22. slovnik = slovnik[section]
  23. else:
  24. if not self:
  25. slovnik['global'] = {}
  26. slovnik = slovnik['global']
  27. parts = line.split(":", 1)
  28. slovnik[parts[0].strip()] = parts[1].strip()
  29.  
  30. def items(self, section):
  31. try:
  32. return self[section]
  33. except KeyError:
  34. return []

The use is simple:

ini = ParseINI('path/to/file.ini')
value = ini['section']['subsection']['key']

.ini parser

ok so if I have this in my setup.ini file:
#---------------------------------------------------------
toolsDir = \tools\scripts\terrainTools\
toolsTempXML = tempSettings.xml
#The image dump is one directory down inside of the toolsDir
imageDump = imageDump\
wildcardSuffix = *_x**_y**.*
tweakDir = \Content\tweak\db\architect\levels\
wipDir = \Content\wip\db\architect\levels\
#[tempLevelSettings] Grrr ... I can't get sections working (not sure why!?)
level = HW_MP_Template_TEST\
#---------------------------------------------------------

I can get ALL the keys to parse into the dict, but they end up in the 'global' section.

If I try to put in the section using the [tempLevelSettings]:

#---------------------------------------------------------
toolsDir = \tools\scripts\terrainTools\
toolsTempXML = tempSettings.xml
#The image dump is one directory down inside of the toolsDir
imageDump = imageDump\
wildcardSuffix = *_x**_y**.*
tweakDir = \Content\tweak\db\architect\levels\
wipDir = \Content\wip\db\architect\levels\
[tempLevelSettings]
level = HW_MP_Template_TEST\
#---------------------------------------------------------

I only get the keys listed AFTER that section in the .ini... but they end up in 'global' and not in 'tempLevelSettings'

Any help?

I did rewrite the class as a fuction:

def buildINISlovnik(filePath):
print 'I am going to read the file:', filePath
#print '-'*65
'''Opens the ini file passed in and logs Key.value pairs in sections to a dictionary.'''
f = open(filePath, 'r')
slovnik = {}
#read each line in the .ini file I want to strip it out because it is a comment, or log it.
for line in f:
#print line #Tell me what's in each line ... for debugging, comment out later
#I want to strip out comments, supported comments are #comment1 and ;comment2
if not line.startswith("#") and not line.startswith(';') and line.strip() != "":
#Keys are set as Key1 = value1, or Key2: value2
line = line.replace('=', ':') #forces all key markers to ':'
line = line.replace(';', '#') #forces all comment markers to '#'
index = line.find('#')
line = line[:index]
line = line.strip()
#Can define sections and grouping, such as [section.subsection.subsubsection]
#Key-value pairs above the first section, are considered global
if line.startswith("["): #looking for sections
sections = line[1:-1].split('.')
for section in sections:
if section not in slovnik:
slovnik[section] = {}
slovnik = slovnik[section]
else:
if 'global' not in slovnik: #key-Value pairs not in sections are logged into global
slovnik['global'] = {}
parts = line.split(":", 1)
slovnik['global'][parts[0].strip()] = parts[1].strip()
print '-'*25, 'done parsing .ini', '-'*25
return slovnik

def main():
filePath = "C:\\spin\\Main\\tools\\scripts\\terrainTools\\setup.ini"
prefsDict = buildINISlovnik(filePath)

if __name__ == "__main__":
main()

Use SimpleConfigParser in Symbian?

is it possible to use SimpleConfigParser as a module in python for Symbian?
I am using PyS60 version 2.0.0

When reading the options from

When reading the options from configuration file they are not in proper sequence as defined in configurationfile