Python Forum

Full Version: opinion: configparser should have been better
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
configparser would have been easier to work with if it had used the dictionary API. i'm not saying not to do what it does, now, but to also do the dictionary API. that is, you would be able to get an option by doing conf[secname][optname] instead of conf.get(secname,optname). that might not seem like much, but you could do if optname in conf[secname]: instead of if conf.has_option(secname,optname):. would that have been so hard to do?

why not abstract that way?
It does
import configparser

parser = configparser.ConfigParser()
parser.read_dict({'section1': {'key1': 'value1',
                               'key2': 'value2',
                                'key3': 'value3'},
                  'section2': {'keyA': 'valueA',
                                'keyB': 'valueB',
                                'keyC': 'valueC'},
                  'section3': {'foo': 'x',
                                'bar': 'y',
                                'baz': 'z'}})
print(parser.sections())
print([option for option in parser['section3']])
print(parser['section3']['foo'])
Output:
['section1', 'section2', 'section3'] ['foo', 'bar', 'baz'] x
but like with dict it's better to use .get() to avoid KeyError and providing default value
i don't need .get or what it provides. modeling this a a dict of some name dicts would have worked better. then i could work with a section by itself as a dict reference. configparser has no means to just reference a section as an object.
you wanted to do conf[secname][optname] and I showed you can.
Also, you can assign section to a name and work with that object.

import configparser
 
parser = configparser.ConfigParser()
parser.read_dict({'section1': {'key1': 'value1',
                               'key2': 'value2',
                                'key3': 'value3'},
                  'section2': {'keyA': 'valueA',
                                'keyB': 'valueB',
                                'keyC': 'valueC'},
                  'section3': {'foo': 'x',
                                'bar': 'y',
                                'baz': 'z'}})

spam = parser['section3']
print(type(spam))
print(spam['bar'])
print(parser['section3']['foo'])
output
Output:
<class 'configparser.SectionProxy'> y x
really don't understand what your problem in this case is
maybe your code is cheating by using .read_dict. show me how by reading from a file, updating an option like and writing it back.
parser['thissection']['thisoption'] = 'thisvalue'
print('thissection now has:',repr(parser['thissection']))
print('these sections exist:',' '.join(k for k in parser['thissection'].keys()))
(Oct-01-2020, 10:58 PM)Skaperen Wrote: [ -> ]maybe your code is cheating by using .read_dict.
It doesn't matter how you populate the configparser.ConfigParser object

create example.ini
Output:
[section1] key1 = value1 key2 = value2 key3 = value3 [section2] keya = valueA keyb = valueB keyc = valueC [section3] foo = x bar = y baz = z
then

import configparser
parser = configparser.ConfigParser()
parser.read('example.ini')
spam = parser['section3']
print(type(spam))
print(spam['bar'])
print(parser['section3']['foo'])
parser['section3']['eggs'] = 'thisvalue'
print('these options exist:',' '.join(k for k in parser['section3'].keys()))
print(parser['section3']['eggs'])
Output:
<class 'configparser.SectionProxy'> y x these options exist: foo bar baz eggs thisvalue
I don't know why you didn't try that to test for yourself before posting
And please, consult the documentation if you are not sure about something - all this is in the examples in the docs at the top under Quick start.
that's still not behaving like 2 layers of dict. all it gives you is access to option values that way. the 2 layers should be splitable so one can do:
favsect = parser[favsectname]
favopts = favsect.keys()
print(f'favorite has options: {" ".join(favopts)}')
features for INI files, such as applying parser.optionxform() to the names, can still be done while implementing as a 2 layers of dict. my library design style is to make library usage simpler even if it means adding more to that library implementation. in this case it would need a class for a section (the inner dictionary) and a class for the INI object (the outer dictionary). that way you can get a reference to just one section at a time and it operates like a dictionary.
Sorry, but I will not continue to participate in this absurd discussion where you just rant, without even trying to try for yourself before posting. And you don't even read what I post. This is my last post in this thread.


I already show you you that you get separate class for section (inner dictionary) - configparser.SectionProxy. The object for the outer dict is the ConfigParser object itself. Below is a code that show it again as well as the functionality you claim (in your last post) that does not exists - configparser.SectionProxy has keys() method and it will return KeysView object


import configparser
parser = configparser.ConfigParser()
parser.read('example.ini')
spam = parser['section3'] # this is section3 object
print(type(spam))
print(spam['bar'])
print(parser['section3']['foo'])
parser['section3']['eggs'] = 'thisvalue'
print('these options exist:',' '.join(k for k in parser['section3'].keys()))
print(parser['section3']['eggs'])
print(spam.keys()) 
print(list(spam.keys()))
Output:
<class 'configparser.SectionProxy'> y x these options exist: foo bar baz eggs thisvalue KeysView(<Section: section3>) ['foo', 'bar', 'baz', 'eggs']
Now, feel free to develop whatever library/API you like and be happy.
when posts show code that is more complicated i don't make an effort to understand it because i don't want to go more complicated. and this thread was not intended for code help as i already did my little project (a command to add or delete profiles in Firefox on Linux/Posix). i'm just saying, in a way, that "Mapping Protocol Access" should not have been an add-on; it should have been the way it was done from the beginning, along with customizing like the .optionxform attribute. a dict already has ways to do defaults like .get(). i'm sure that if configparser had not existed and i implemented it some other way, i would have been accused of pythonic heresy.