我已阅读此post,并在subscriber.ini中定义了一个数组
[smtp]
subscriber[] = aaa@hotmail.com
subscriber[] = bbb@XX.webmail
subscriber[] = ccc@test.org
然后我尝试使用ConfigParser来读取数组
#!/usr/bin/python
import ConfigParser
CONFIG_FILE = 'subscriber.ini'
config = ConfigParser.ConfigParser()
config.read( CONFIG_FILE )
subscriber = config.get('smtp' , 'subscriber[]' )
print subscriber
它将输出最后一个元素ccc@test.org。但我希望有一个完整的用户名单。
如何从ini文件中获取数组?
答案 0 :(得分:5)
此subscriber[]
自动将subscriber
变为多个值列表的语法一般不是.ini文件的功能,也不是ConfigParser的功能。它是Zend_Config_Ini
的一个特征。
在Python中,ConfigParser
ini文件创建一个dict,将每个键映射到其值。如果您有多个值,它将覆盖以前的值。神奇的[]
后缀毫无意义。
但是,ConfigParser
构造函数允许您指定自定义字典类型或工厂,而不是默认的OrderedDict
。
一个简单的解决方案是使用defaultdict(list)
(或OrderedDefaultDict,其中有文档中的配方)用于底层存储,__setitem__(self, key, value)
执行self.dd[key].append(value)
和委托一切正常。 (或者,如果您愿意,继承自defaultdict
,则覆盖构造函数以将list
传递给超级,然后只是不要覆盖除__setitem__
之外的任何内容。)这将使将所有值列入列表。
你甚至可以做一些hacky,其中只有一次看到的值是单个值,但如果再次看到相同的名称,它就会成为一个列表。我认为这将是一个糟糕的想法(你真的想检查config.get('smtp', 'subscriber[]')
的类型来决定你是否要迭代它吗?),但如果你愿意,How to ConfigParse a file keeping multiple values for identical keys?显示如何
然而,重复你正在寻找的确切魔法并不是很难,其中以[]
结尾的所有键都是列表(无论它们出现一次还是多次),其他一切都像普通一样(如果多次出现,则仅保留最后一个值)。像这样:
class MultiDict(collections.OrderedDict):
def __setitem__(self, key, value):
if key.endswith('[]'):
super(MultiDict, self).setdefault(key, []).append(value)
else:
super(MultiDict, self).__setitem__(key, value)
这显然不会提供Zend_Config_Ini
在普通.ini文件之上添加的扩展功能的所有。例如,[group : subgroup : subsub]
作为组名称没有任何特殊含义,key.subkey.subsub
也不会作为键名。 PHP值TRUE
,FALSE
,yes
,no
和NULL
不会转换为Python值True
,{{1} },False
,True
和False
。数字不会神奇地成为数字。 (实际上,这不是None
的一个特征,而是PHP错误输入的错误。)你必须使用Zend_Config_Ini
条评论,而不是自由地混合#
,{{1} }和#
。等等。您要添加的任何功能都必须手动添加,就像您执行此操作一样。
正如我在评论中所建议的那样,如果你真的想拥有两个以上的层次结构,那么你可能会更好地使用自然无限分层的格式,其中任何值都可以是其他值的列表或字典。< / p>
JSON现在无处不在。它可能不像INI那样具有人类可编辑性,但我认为2014年有更多人比INI更熟悉它。它具有巨大的优势,它是标准化格式,Python(2.6+)和PHP(5.2) +)在标准库中附带解析器和漂亮的打印机。
YAML是一种更灵活,人性化的格式。但是您需要使用这两种语言的第三方模块(请参阅YAML网站上的列表)。如果你不小心,它也会带来一些安全问题。 (请参阅;
文档中的//
和朋友;大多数其他图书馆都有相似的功能。)
答案 1 :(得分:4)
Python ConfigParser不提供此功能。请改用以下代码:
[smtp]
subscriber = aaa@hotmail.com bbb@XX.webmail ccc@test.org
然后在你的剧本中:
subscriber = config.get('smtp' , 'subscriber').split()
答案 2 :(得分:1)
我想知道你是否考虑过使用Michael Foord的configobj module?它似乎有能力 做你想做的事情,试图阻止ConfigParser做你显然需要的事情可能会更好。