ConfigObj与单元素列表

2 投票
2 回答
1058 浏览
提问于 2025-04-18 18:56

我在研究ConfigObj的时候,遇到了一个关于验证和单元素列表的问题。假设我有一个配置规范,长得像这样:

config_specification = """[Data]
  [[__many__]]
    type = option('sense.xml')
    transport = string
    sensors = list
      [[[Identifier]]]
        type = option("name", "mac", "uuid")
        adapter = string(default='')
        name = string(default='')
        file = string(default='')"""

这个列表其实可以只有一个元素,也可以有多个元素。我可以很简单地添加多个元素:

[Data]
  [[primary]]
    type = sense.xml
    transport = $http
    sensors = $virtual, $gpio, $adc
      [[[Identifier]]]
        type = name
        name = VirtualRelay01

但是,下面这个是无效的。它不会把它转换成一个包含1个元素的列表:

sensors = $virtual

我尝试了几种不同的写法。这种写法不行:

sensors = {$virtual}

这个也不行:

sensors = [$virtual]

如果我这样做,它却给我返回了一个包含两个元素的列表!其中一个是空字符串:

sensors = ($virtual,)

我有好几个这样的部分,并且我把它们放在一个循环里。我把它们应用到只接受列表的类上,我不想一个个地写代码来处理这些特殊情况(更不用说,这样会导致验证失败)。

为了完整起见,这里是我如何进行验证的:

cfg = ConfigObj(filename, configspec=config_specification.split('\n'))

test = cfg.validate(Validator())

valid = True
for (section_list, key, _) in flatten_errors(cfg, test):
  if key is not None:
    print('Invalid value for key {0} in section {1}'.format(key,', '.join(section_list)))
    valid = False
  else:
    print('Section {0} failed validation'.format(', '.join(section_list)))
    valid = False
if not valid:
  exit(3)

2 个回答

1

根据文档,如果你最终想要的是一个字符串,那么在你的配置规范中,你可以直接使用sensors = force_list(),这样就不需要在只有一个元素的列表后面加上奇怪的逗号了。

4

我是configobj的开发者之一。根据这个单元测试的这一行,我认为sensors = $virtual,应该能按你预期的那样工作。

我不太确定($virtual,)返回一个包含两个元素的列表这件事是否合理。这听起来有点不对。如果你想不出什么场景是需要隐含的空字符串,那可能值得提个问题。

撰写回答