将ConfigParser值转换为Python数据类型
ConfigParser
这个工具要求所有的部分、键和数值都必须是字符串,这一点并不奇怪。它有一些方法可以把这些字符串转换成其他数据类型,比如 getfloat
用来获取浮点数,getint
用来获取整数,getboolean
用来获取布尔值。如果你不知道数据的类型,可以用 eval()
把 get()
包裹起来,这样就可以把字符串进行评估,比如:
>>> from ConfigParser import SafeConfigParser
>>> cp = SafeConfigParser()
>>> cp.add_section('one')
>>> cp.set('one', 'key', '42')
>>> print cp.get('one', 'key')
'42'
>>> print eval(cp.get('one', 'key'))
42
>>> cp.set('one', 'key', 'None')
>>> print eval(cp.get('one', 'key'))
None
>>>
有没有更好的方法呢?我想这可能会有一些严重的安全隐患,因为从文件中评估文本是有风险的——我承认这一点;不过我完全信任这个文件。
我本来想用 pickle
来处理这个,但我真的希望配置文件能让人看得懂。
你会怎么做呢?
6 个回答
这里还有另一个解决方案。你可以创建一个 getany()
方法,它会自动识别并返回大多数数据类型的正确类型,包括 str
(字符串)、int
(整数)、float
(浮点数)、bool
(布尔值)和 None
(空值)。
需要注意的是,配置文件中的表示法必须是Python格式,这样才能正常工作。例如,布尔值的真要写成 True
,空值要写成 None
。
from ast import literal_eval
import configparser
parser = configparser.ConfigParser(converters={"any": lambda x: literal_eval(x)})
value = parser.getany("section", "key")
# ...
如果你在寻找一个更简单的解决办法,而不是自己去转换数据类型,你可以使用 localconfig 这个模块,它会帮你自动转换。这个转换是通过根据值来猜测数据类型来完成的(比如,123 是整数,123.4 是浮点数,true 是布尔值,等等)。
下面是一个跟提问者的例子类似的示例:
>>> from localconfig import config
>>> config.read('[one]\nkey = 42\nkey2 = None')
>>> config.one.key, type(config.one.key)
(42, <type 'int'>)
>>> config.one.key2, type(config.one.key2)
(None, <type 'NoneType'>)
>>> config.get('one', 'key'), config.get('one', 'key2')
(42, None)
这个模块是基于 ConfigParser 的,所以它完全兼容。
你可以在这里查看它: https://pypi.python.org/pypi/localconfig
如果你使用的是Python 2.6或更高版本,可以使用ast.literal_eval
这个功能:
ast.literal_eval(node_or_string)
这个功能可以安全地评估一个表达式节点或者一个包含Python表达式的字符串。你提供的字符串或节点只能包含以下几种Python的基本数据结构:字符串、数字、元组、列表、字典、布尔值和None。这个功能可以用来安全地评估来自不可信来源的包含Python表达式的字符串,而不需要自己去解析这些值。
当字符串是安全的时,它的工作方式和eval
是一样的:
>>> literal_eval("{'key': 10}")
{'key': 10}
但是如果出现文档中没有列出的其他类型,它就会失败:
>>> literal_eval("import os; os.system('rm -rf somepath')")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.6/ast.py", line 49, in literal_eval
node_or_string = parse(node_or_string, mode='eval')
File "/usr/lib64/python2.6/ast.py", line 37, in parse
return compile(expr, filename, mode, PyCF_ONLY_AST)
File "<unknown>", line 1
import os; os.system('rm -rf somepath')
^
SyntaxError: invalid syntax