Python INI File Parser

A flexible INI parser can be built in Python. Although tools to do this already exist, it’s important to understand how this might be done in the general case to learn new python techniques in general.

The idea is to parse rudimentary INI files of the form:

Field 1: Foo
Field 2: Bar

Flat INI File Format

In this example we will ignore INI groupings and stick with just the INI name-value pairs.

The challenge is in writing a system that maps from INI names to variable names. The application can also be built with flexible punctuation. For instance:

class ini_parser:
    ini = 'test.ini'
    ini_sep = ':'
    ini_mapping = {
        'Field 1': 'field_1',
        'Field 2': 'field_2'
    }

Code to implement a generic INI parser in Python.

In this example, the INI uses names with spaces. Since Python variable names cannot have spaces, the mapping is necessary to allow for dissimilar local variable names relative to the name used in the INI file.

Once we have this boilerplate, we can build an iniparser around it:

def parse_ini(self):
    with open(self.ini) as file_obj:
        for line in file_obj:
            if self.ini_sep in line:
                # Split and trim whitespace around fields
                name, value = tuple([x.strip() for x in l.split(self.ini_sep, 1)])
                setattr(self, self.ini_mapping[name], value)

ini_parser.parse_ini()

In the above example, self.field_1 would get the value 'Foo', and self.field_2 would get the value 'Bar'. The code only looks at the first colon in the line of an INI file, so that INI names can’t contain colons (:), but any subsequent colon (:) is considered part of the value.

Once software makes changes to an applications settings, it’s important to write those changes back to the INI file:

def write_ini(self):
    with open(self.ini, ‘w’) as file_obj:
        for ini_name, local_name in self.ini_mapping.items():
            value = getattr(self, local_name)
            file_obj.write(ini_name + self.ini_sep + ‘ ‘ + value)

ini_parser.write_ini()

Note, for this simple parser, all values will be returned as strings. One could add a type to the ini_parser.ini_mappings to also provide a type for the variable to be assigned, casting value to it. Alternatively, if the variable to be set already exists and has a type, the type command can be used to get that type and then cast value to that type.

Further, if a list type is included in the INI, for instance a series of comma-separated values, then a special list handler will have to be written which will split and strip each value by commas (,) and then join them again with commas (,) when writing. Because lists can be single-element, it’s impossible for software to know by simply searching for commas (,) whether an INI value is a list or not. This is why the type must be included in some way internally to parse list values properly. The code to do this is left as an exercise for the reader.

I hope you enjoyed this little tutorial. Please note, I am available for hire if you like what you see!