使用ConfigParser从ini文件读取数组 [英] Use ConfigParser to read an array from ini file
问题描述
我已阅读 post ,并在subscriber.ini中定义了一个数组
I have read this post, and defined an array in subscriber.ini
[smtp]
subscriber[] = aaa@hotmail.com
subscriber[] = bbb@XX.webmail
subscriber[] = ccc@test.org
然后我尝试使用ConfigParser读取数组
Then I try to use ConfigParser to read the array
#!/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。但是我希望有完整的订户列表。
It will output the last element, ccc@test.org. But I expect a full subscriber list.
如何从ini文件中获取数组?
How do I get the array from ini file ?
推荐答案
此语法,其中 subscriber []
自动使 subscriber
成为多个值的列表,通常不是.ini文件的功能,也不是 ConfigParser 的功能;它是 Zend_Config_Ini
。
This syntax, where subscriber[]
automatically makes subscriber
into a list of multiple values, is not a feature of .ini files in general, nor of ConfigParser; it's a feature of Zend_Config_Ini
.
在Python中, ConfigParser
ini文件会创建字典映射每个价值的关键。如果您有多个值,它将覆盖先前的值。神奇的后缀 []
毫无意义。
In Python, a ConfigParser
ini file creates a dict mapping each key to its value. If you have more than one value, it will just override previous values. The magic []
suffix means nothing.
不过, ConfigParser
构造函数使您可以指定自定义词典类型或工厂,以代替默认的 OrderedDict
。
However, the ConfigParser
constructor lets you specify a custom dictionary type or factory, in place of the default OrderedDict
.
一个简单的解决方案是使用 defaultdict(list)
(或OrderedDefaultDict,其中有一些用于在文档中)作为基础存储,具有 __ setitem __(self,key,value)
做 self.dd [key] .append(value)
,然后正常委派其他所有内容。 (或者,如果愿意,可以从 defaultdict
继承,重写构造函数以将 list
传递给超级对象,然后除了 __ setitem __
之外,不要覆盖其他任何内容。)这会将 all 个值全部放入列表中。
One simple solution would be to use a defaultdict(list)
(or an OrderedDefaultDict, which there are recipes for in the docs) for the underlying storage, have __setitem__(self, key, value)
do self.dd[key].append(value)
, and delegate everything else normally. (Or, if you prefer, inherit from defaultdict
, override the constructor to pass list
to the super, and then just don't override anything but __setitem__
.) That will make all of your values into lists.
您甚至可以做一些骇人听闻的事情,其中只有一次看到的值是单个值,但是如果再次看到相同的名称,它将成为一个列表。我认为这将是一个糟糕的主意(您是否真的要检查 config.get('smtp','subscriber []')
的类型,以确定是否您是否要对其进行迭代?),但是如果您想如何配置一个文件,为一个相同的键保留多个值?显示了如何。
You could even do something hacky where a value that's only seen once is a single value, but if you see the same name again it becomes a list. I think that would be a terrible idea (do you really want to check the type of config.get('smtp', 'subscriber[]')
to decide whether or not you want to iterate over it?), but if you want to, How to ConfigParse a file keeping multiple values for identical keys? shows how.
但是,重现精确值并不难您正在寻找的魔术,所有以 []
结尾的键都是列表(无论它们出现一次还是多次),其他所有内容都像正常一样(仅保留最后一个)值(如果出现多次)。像这样的东西:
However, it's not at all hard to reproduce the exact magic you're looking for, where all keys ending in []
are lists (whether they appear once or multiple times), and everything else works like normal (keeps only the last value if it appears multiple times). Something like this:
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)
这显然不会提供 all 的所有扩展功能,这些扩展功能是 Zend_Config_Ini
在普通.ini文件之上添加的。例如, [group:subgroup:subsub]
作为组名将没有任何特殊含义, key.subkey.subsub 作为键名。 PHP值
TRUE
, FALSE
,是
,否
和 NULL
不会转换为Python值 True
, False
, True
, False
和无
。数字不会神奇地变成数字。 (实际上,这不是 Zend_Config_Ini
的功能,而是PHP泄漏类型的错误特征。)您必须使用#
注释,而不是随意混合#
,;
和 //
。等等。您想要添加的任何这些功能,都必须像执行此操作一样手动添加。
This obviously won't provide all of the extended features that Zend_Config_Ini
adds on top of normal .ini files. For example, [group : subgroup : subsub]
won't have any special meaning as a group name, nor will key.subkey.subsub
as a key name. PHP values TRUE
, FALSE
, yes
, no
, and NULL
won't get converted to Python values True
, False
, True
, False
, and None
. Numbers won't magically become numbers. (Actually, this isn't a feature of Zend_Config_Ini
, but a misfeature of PHP's leaky typing.) You have to use #
comments, rather than freely mixing #
, ;
, and //
. And so on. Any of those features that you want to add, you'll have to add manually, just as you did this one.
正如我在评论中建议的那样,如果您确实如果希望具有两个以上的层次结构,则最好使用自然无限的层次结构格式,其中任何值都可以是其他值的列表或字典。
As I suggested in a comment, if you really want to have more than two levels of hierarchy, you may be better off with a naturally infinitely-hierarchical format, where any value can be a list or dict of other values.
JSON 如今无处不在。它可能不像INI那样可人工编辑,但我认为它比2014年的INI熟悉的人更多。它具有标准格式以及Python(2.6+)和PHP(5.2)的巨大优势。 +)在其标准库中随附解析器和漂亮打印机。
JSON is ubiquitous nowadays. It may not be quite as human-editable as INI, but I think more people are familiar with it than INI in 2014. And it has the huge advantage that it's a standardized format, and that both Python (2.6+) and PHP (5.2+) come with parsers and pretty-printers for in their standard libraries.
YAML 是一种更灵活且可人工修改的格式。但是您将需要两种语言的第三方模块(请参见YAML网站上的列表)。如果您不小心,它也会带来一些安全隐患。 (请参见 中的
文档;大多数其他库具有类似的功能。) safe_load
和朋友。 PyYAML
YAML is a more flexible and human-editable format. But you will need third-party modules in both languages (see the list at the YAML site). And it can also bring in some security concerns if you're not careful. (See safe_load
and friends in the PyYAML
docs; most other libraries have similar features.)
这篇关于使用ConfigParser从ini文件读取数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!