问题描述
我已阅读,并在subscriber.ini中定义了一个数组
I have read this post, and defined an array in subscriber.ini
[smtp] subscriber[] = [email protected] subscriber[] = [email protected] subscriber[] = [email protected]
然后我尝试使用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
它将输出最后一个元素[email protected]。但是我希望有完整的订户列表。
It will output the last element, [email protected]. But I expect a full subscriber list.
如何从ini文件中获取数组?
How do I get the array from ini file ?
推荐答案
此语法,其中 subscriber [] 自动使 subscriber 成为多个值的列表,通常不是.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.
如今无处不在。它可能不像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 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文件读取数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!