Viggar
Viggar

Reputation: 170

Parse numbers and lists from config files with configparser

I'm doing a relatively big project for my final thesis and therefore I am using a .ini file for storing and retrieving settings. However, I am unable to find an elegant solution for how to convert the strings (well, actually the strings inside the dictionary) that Configparser returns to numbers (ints and floats) and/or lists.

Googling the issue, I came across this SO thread which only tackles the 'list' part of my problem but using the top rated solution (defining lists inside the .ini file like that: list=item1,item2) didn't do anything for me, as the 'list' still shows up as a string after parsing. Also, I do not want to change format.

So I decided I would try it myself and came up with this solution:

import configparser 

# create a new instance of a 'ConfigParser' class
config = configparser.ConfigParser()
# create mock-content for the config file
config["Test"] = {
"test_string":"string",
"test_int":"2",
"test_float":"3.0",
"test_list":"item1, item2"
}
# get the relevant settings
settings = config["Test"]
# pack the relevant settings into a dictionary
settings = dict(settings)
# iterate through all the key-value pairs and convert them, if possible
for key, value in settings.items():
    # try to convert to int
    try:
        settings[key] = int(value)
    # if the value can't be converted to int, it might be a float or a list
    except ValueError:
        # try converting it to a float
        try:
            settings[key] = float(value)
        # if the value can't be converted to float, try converting to list
        except ValueError:
            if "," in value:
                cont = value.split(",")
                settings[key] = [item.strip() for item in cont]
            else:
                settings[key] = value
print(type(settings["test_string"]))
print(settings)

However, this seems so very inelegant and is so heavily nested and the task itself seems so important that I cannot believe that there is no "more official" solution to this that I am simply unable to find.

So, could please someone help me out here and tell me if there really is no better, more straightforward way to achieve this!?

Upvotes: 1

Views: 1099

Answers (1)

Jarvis
Jarvis

Reputation: 8564

Best I can do is this (though it's kinda hacky and probably dangerous too):

for key, value in settings.items():
    try: # will handle both ints and floats, even tuples with ints/floats
        settings[key] = eval(value)
    except NameError: # this means it's a string or a tuple with strings
        get_val = list(map(str.strip, value.split(",")))
        settings[key] = get_val if get_val[1:] else get_val[0]

This will work correctly for ints, floats as well as your comma separated values (it will evaluated it as a tuple, I guess that should be fine though I added a condition for that anyway).

Upvotes: 2

Related Questions