Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python configparser: get list of unused entries

I am using Python's configparser to read an ini file.

After parsing, I would like to print a list of entries that have not been used by the parser to inform the user that they have added entries to their ini file that will be ignored.

Consider an ini file like this:

[DEFAULT]
param1 = 1
param2 = 2
param3 = 3
param4 = 4

What I would like to have is this:

parser = configparser.ConfigParser()
parser.read(config_path)    
p1 = parser["DEFAULT"]["param1"]
p2 = parser["DEFAULT"]["param2"]
unused = parser["DEFAULT"].get_unused_keys()

The last line is made up. I would like the variable 'unused' to contain

["param3", "param4"]

I haven't found any mention of such a feature in the manual, but I would find it very helpful. I could inherit from ConfigParser and extend all access functions to have a flag that keeps track of whether a specific item was accessed, but I was hoping there is a simpler way.

like image 527
Cerno Avatar asked Oct 26 '25 13:10

Cerno


1 Answers

I have written a solution. It is not too elegant but it works. You need to create a child class from RawConfigParser class and create a dict variable in your class and extend the get, _get methods. As you can see below when you use the get, getint, getfloat, getboolean methods to get a value of variable then the related method appends the section and variable to your dict. When you call the get_unused_keys method, it will filter the all available options in a section with the already used options and gives the unused options.

Complete code:

try:
    import ConfigParser as Cp
except ImportError:
    import configparser as Cp


class ConfigParser(Cp.RawConfigParser):
    """
    ConfigParser class contains the all ConfigParser related implementations.
    """

    used_vars = {}

    def get_unused_keys(self, section):
        all_sections = self.options(section)
        unused_options = [x for x in all_sections if x not in self.used_vars[section]]
        return unused_options

    def get(self, section, option, *, raw=False, vars=None, fallback=Cp._UNSET):
        if section not in self.used_vars:
            self.used_vars[section] = [option]
        else:
            self.used_vars[section].append(option)
        return super().get(section, option, raw=raw, vars=vars, fallback=fallback)

    def _get(self, section, conv, option, **kwargs):
        if section not in self.used_vars:
            self.used_vars[section] = [option]
        else:
            self.used_vars[section].append(option)
        return super()._get(section, conv, option, **kwargs)


parser = ConfigParser()
parser.read("test.ini")

p1 = parser.getint(section="TEST", option="param1")
print("TEST section - param1 = {}".format(p1))
p2 = parser.getboolean(section="TEST", option="param2")
print("TEST section - param2 = {}".format(p2))
print("Unused options in 'TEST' section: {}".format(parser.get_unused_keys("TEST")))
print("")
par2 = parser.get(section="TEST_SEC", option="param2")
print("TEST_SEC section - param2 = {}".format(par2))
print("Unused options in 'TEST_SEC' section: {}".format(parser.get_unused_keys("TEST_SEC")))

Used ini file:

[TEST]
param1 = 1
param2 = True
param3 = 3
param4 = False

[TEST_SEC]
param1 = 89
param2 = Hello World
param3 = 655

OUTPUT:

>>> python3 test.py 
TEST section - param1 = 1
TEST section - param2 = True
Unused options in 'TEST' section: ['param3', 'param4']

TEST_SEC section - param2 = Hello World
Unused options in 'TEST_SEC' section: ['param1', 'param3']

FYI:

You shouldn't use DEFAULT as name of section because it is a special section and you can get unexpected behavior. I have added _get method to my implementations. If you check the original implementation of ConfigParser, you can see all type specific getter use this method so it is enough to change. It means now the implementation supports getint, getfloat, getboolean methods as well. I hope my answer help you!

like image 181
milanbalazs Avatar answered Oct 28 '25 04:10

milanbalazs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!