python ConfigObj选项验证

nszi6y05  于 2023-02-07  发布在  Python
关注(0)|答案(2)|浏览(115)

我正在使用ConfigObj和Validator解析python中的一个配置文件,虽然我很喜欢这个工具,但我在使用configSpec文件进行验证时遇到了一些问题,我使用的option()configSpec类型强制从一个受控词汇表中选择值:

output_mode = option("Verbose", "Terse", "Silent")

我想让我的代码知道用户何时输入了不在CV中的选项。据我所知,Validator似乎只说明了哪个配置键验证失败,但没有说明失败的原因:

from configobj import ConfigObj, flatten_errors
from validate import Validator

config = ConfigObj('config.ini', configspec='configspec.ini')
validator = Validator()
results = config.validate(validator)

if results != True:
    for (section_list, key, _) in flatten_errors(config, results):
        if key is not None:
            print 'The "%s" key in the section "%s" failed validation' % (key, ', '.join(section_list))
        else:
            print 'The following section was missing:%s ' % ', '.join(section_list)

这个代码片段可以工作,但是有很多原因导致键验证失败,从不在整数范围内到不在CV中。我不想询问键名,并根据该键的失败情况引发不同类型的异常。有没有更干净的方法来处理特定类型的验证错误?
长时间stackoverflow读者,第一次海报:-)

fgw7neuy

fgw7neuy1#

更新:我认为这是我想要做的。关键是配置对象将错误存储为Exceptions,然后可以针对子类ValidateError检查这些异常。这样你就只需要对每个子类做一次检查,而不是对每个参数值做一次检查。如果验证失败时抛出一个异常可能会更好,但可能会失去其他功能。

self.config = configobj.ConfigObj(configFile, configspec=self.getConfigSpecFile())
validator = Validator()
results = self.config.validate(validator, preserve_errors=True)

for entry in flatten_errors(self.config, results):

   [sectionList, key, error] = entry
   if error == False:
      msg = "The parameter %s was not in the config file\n" % key
      msg += "Please check to make sure this parameter is present and there are no mis-spellings."
      raise ConfigException(msg)

   if key is not None:
      if isinstance(error, VdtValueError):
         optionString = self.config.configspec[key]
         msg = "The parameter %s was set to %s which is not one of the allowed values\n" % (key, self.config[key])
         msg += "Please set the value to be in %s" % optionString
         raise ConfigException(msg)

OptionString只是一个形式为option的字符串(“option 1”,“option 2”),而不是一个列表,因此要使它看起来更漂亮,您需要获取()中的子字符串。

qnakjoqk

qnakjoqk2#

为便于感兴趣的人员将来参考,您还应检查无关数据。这可以在extra_values属性中找到。完整的示例可能是:

from configobj import ConfigObj, ConfigObjError, flatten_errors
from validate import Validator, VdtValueError

def check_extra(config, results):
    "Recursive function for checking extra sections and values"

    if isinstance(results, bool):
        return ""

    parentname = ""
    cfg=config
    while cfg.name is not None:
        parentname=f"[{cfg.name}]" + parentname
        cfg = cfg.parent
    if parentname != "":
        parentname = f" in section {parentname}"

    if config.extra_values:
        wmsg = f"\nValues defined{parentname} but not in specification:\n    {config.extra_values}"
    else:
        wmsg=""
    for s in config.sections:
        if s not in results.keys():
            wmsg += f"\n{'['+s+']':>20s} section found{parentname} but not in specification"
        else:
            wmsg += check_extra(config[s], results[s])
    return wmsg

def load_config(configfile, configspec):
    "Load and check configvale acccording to spec"

    config = ConfigObj(configfile, file_error=True, configspec=configspec)
    validator = Validator()
    results = config.validate(validator, preserve_errors=True)

    msg = ""
    fatalerr = False

    for entry in flatten_errors(config, results):

        [sectionList, key, error] = entry
        if error is False:
            msg += f"\n{key:>30s} missing in section [{']['.join(sectionList)}]"
            fatalerr = True

        if key is not None:
            if isinstance(error, VdtValueError):
                optionString = config.configspec[key]
                msg += f"\nThe parameter {key} was set to {[config[s][key] for s in sectionList]} which is not one of the allowed values\n"
                msg += "    Please set the value to be in %s" % optionString
                fatalerr = True

    # Verifying extraneous values"
    wmsg = check_extra(config, results)
    if wmsg != "":
        print(f"WARNINGS found in configuration file {configfile}")
        print(wmsg)

    if fatalerr:
        print(f"ERRORS found in configuration file {configfile}")
        raise RuntimeError(msg)

    print(f'Configuration {configfile} validated successfully')

if __name__ == "__main__":

    configfile="myconfig.cfg"
    configspec="myconfig_spec.cfg"

    load_config(configfile, configspec)

相关问题