Search code examples
pythonoopconfigparser

Using Configparser to create objects of a class?


I'm a little stumped on how to do this.

Let's say I have a employees.ini file that looks like this:

[amber]
sex=female
age=29
location=usa
income=60000
debt=300

[john]
sex=male
age=19
location=usa
income=19000
debt=nan

I have a for loop to access each piece of information and assign to a variable.

from configparser import ConfigParser
config=ConfigParser()
config.read('employees.ini')
for section in config.sections():
    name=section
    sex=config[section]['sex']
    age=config[section]['age']
    location=config[section]['location']
    income=config[section]['income']
    debt=config[section]['debt']

I also have a class where each section can be accepted as an object:

class Users:
    def __init__(self, name, sex, age, location, debt):
        self.__name=name
        self.__sex=sex
        self.__age=age
        self.__location=location
        self.__income=income
        self.__debt=debt

    def foo(self):
        do a thing

    def bar(self):
        do a different thing ...

My hope was to now be able to access amber.foo and john.bar. However, I'm struggling on how to pass the variables out of the for loop into the class before they are overwritten by the next iteration of the loop. I feel like I might be overthinking this one.

My thought was this would make the code much more user friendly as a bulk of the code could be left untouched and only the .ini would need to be updated when a new user is needed.

Thanks for any help you could give.


Solution

  • I would add a class method to parse the configuration file data into a new object.

    class User:
        def __init__(self, name, sex, age, location, debt):
            self.__name=name
            self.__sex=sex
            self.__age=age
            self.__location=location
            self.__income=income
            self.__debt=debt
    
        @classmethod
        def from_config(cls, name, config):
            return cls(name, config['sex'], config['age'], config['location'], config['debt']
    
        def foo(self):
            do a thing
    
        def bar(self):
            do a different thing ...
    

    Now the details of how to actually create an instance of User are abstracted away in the class itself; the code that iterates through the configuration need only pass the relevant data to the class method.

    from configparser import ConfigParser
    config=ConfigParser()
    
    config.read('employees.ini')
    users = [User.from_config(section, config[section]) for section in config.sections()]
    

    Since your class uses the key names of configuration file as parameter names, you could just unpack the dict and use __init__ directly instead of defining a class method.

    from configparser import ConfigParser
    config=ConfigParser()
    
    config.read('employees.ini')
    users = [User(section, **config[section]) for section in config.sections()]