简体   繁体   中英

Python ConfigParser efficient way to check if an option is empty

Below is my sample configuration file

[HEAD1]
key1 = val1
key2 = val2

[HEAD2]
key1 = 
key2 = val2

I want to write an efficient code that would throw an error to the user indicating if any option lacks value (if it is empty not given value after '=')

I am using Python ConfigParser module

import ConfigParser
config = ConfigParser.RawConfigParser()
config.read("./mytest.cfg")
for section in config.sections():
    for option in config.options(section):
        if not config.get(section, option):
           print "Option: %s has no value under section %s" %(option,section)

I will be glad to know if any efficient method to quickly identify the same instead of iterating with 2 loops.

From the parser's perspective, the option key1 in section HEAD2 does have a value; an empty string instance, which constitutes a valid value for the parser:

print repr(config.get('HEAD2', 'key1'))
# Output: ''

You could subclass RawConfigParser and overwrite the _read() method to catch these empty string values before they are insterted into the internal dict. However, _read is quite lengthy and capturing the unwanted values in there appears a bit clumsy. I would only go down that road if my Python version was below 2.6.
In this scenario, you would a add a check for an empty string while processing option lines

if optval == '':
    print "Option: %s has no value under section %s" % (optname, cursect['__name__'])

after empty values have been handled .


As of Python 2.6, RawConfigParser (and descendants thereof) takes an optional argument dict_type , which allows you to pass in a custom dictionary class, that the parser will use internally.
As of Python 2.7, the default is collections.OrderedDict with a fallback to the builtin dict .
You could create a custom dict class that warns about empty string instances as values:

# as done in ConfigParser
try:
    from collections import OrderedDict as _default_dict
except ImportError:
    # fallback for setup.py which hasn't yet built _collections
    _default_dict = dict


class NotifyEmptyStringValueDict(_default_dict):

    def __setitem__(self, key, value):
        if value == "":
            # Consider raising an exception here instead, e.g. ValueError,
            # unless you don't want empty string values to break the parsing
            # and just want a warning message to be displayed while parsing continues
            print "Option: %s has no value under section %s" % (key, self['__name__'])
            # accessing self['__name__'] obviously raises a KeyError when used
            # outside the context of a parser instance. In a parser, this holds
            # the section name
        _default_dict.__setitem__(self, key, value)

Then instantiate your parser with this class as dict_type :

config = ConfigParser.RawConfigParser(dict_type=NotifyEmptyStringValueDict)
config.read("./mytest.cfg")

Both options, overwriting _read in a subclass of RawConfigParser in Python < 2.6 and using a custom mutable mapping type as dict_type in Python >= 2.6, have the advantage that the check is already performed while the config is parsed; no need to iterate through the completely parsed config again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM