Everytime you try to get or set to a section using configparser
in Python it throws a NoSectionError
if the section does not exist. Is there anyway to avoid this?
Also, can I also avoid the NoOptionError
when getting an option?
For example, using a dictionary, there is the setdefault
option: instead of throwing a KeyError
when the key does not exist, the dictionary adds the key, sets the key's value to the default value, and returns the default value.
I am currently doing the following for getting attributes:
def read_config(section):
config = configparser.ConfigParser()
config.read(location)
try:
apple = config.get(section, 'apple')
except NoSectionError, NoOptionError:
apple = None
try:
pear = config.get(section, 'pear')
except NoSectionError, NoOptionError:
pear = None
try:
banana = config(section, 'banana')
except NoSectionError, NoOptionError:
banana = None
return apple, pear, banana
And the following for setting them:
def save_to_config(section, apple, pear, banana):
config = configparser.ConfigParser()
if not os.path.exists(folder_location):
os.makedirs(folder_location)
config.read(location)
if section not in config.sections():
config.add_section(section)
config.set(section, 'apple', apple)
config.set(section, 'pear', pear)
config.set(section, 'banana', banana)
Setting isn't too bad because they all have the same section, but getting is well... terrible. There has got to be a better way.
Is there perhaps some one liner where I can reduce this:
try:
apple = config.get(section, 'apple')
except NoSectionError, NoOptionError:
apple = None
to this:
apple = config.get_with_default(section, 'apple', None)
-- EDIT --
I have tried to make the following changes per lego's suggestion:
def read_config(section):
defaults = { section : {'apple': None,
'pear': None,
'banana': None }}
config = configparser.ConfigParser(defaults = defaults)
config.read(location)
apple = config.get(section, 'apple')
pear = config.get(section, 'pear')
banana = config(section, 'banana')
return apple, pear, banana
But this still raises a NoSectionError
if the section doesn't exist
Note: I have also tried it where defaults = just {'apple': None, 'pear': None, 'banana': None }
(no section)
There a few ways to handle this depending on how complex you want to get.
The simplest way is probably just chaining logic together. ConfigParser
defines has_option
to safely check if an option exists for a section.
apple = config.has_option(section,'apple') and config.get(section,'apple') or None
Alternatively, if you know ahead of time which options should have values you can set the defaults
dictionary when instantiating the parser. This has the advantage of retaining and raising any errors for sections you don't know about.
myDefaults = {'apple':None,'banana':None,'pear':None}
config = configparser.ConfigParser(defaults=myDefaults)
As stated by Wogan you can create a wrapper function, but you can easily just again use has_option
like so:
def get_with_default(config,section,name,default)
if config.has_option(section,name):
return config.get(section,name)
else:
return default