ConfigParser
要求所有部分、键和值都是字符串;没有惊喜。它具有将值转换为数据类型的方法,包括 getfloat
、getint
、getboolean
。如果您不知道数据类型,可以用 get()
包裹 eval()
来评估字符串,例如:
>>> 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
来实现这一点,但我真的很想让配置文件保持可读性。
你会怎么做?
如果您使用的是 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
这是另一种解决方案。您可以生成一个
getany()
方法,该方法将自动检测并返回大多数类型的正确数据类型,包括 str
、int
、float
、bool
和 None
。
请注意,配置文件中的符号必须是 Python 才能正常工作。例如
True
表示布尔值 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 是 int,123.4 是 float,true 是 bool,等等)。
这是 OP 之后的示例:
>>> 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 之上的包装器,因此完全兼容。
如果您使用的是 2.7+,则可以使用
.getint
.getfloat
.getbool
方法。您可以在 docs 中了解有关它们的更多信息
因此您的应用程序将使用
print cp.getint('one', 'key')
查看 ConfigIt 以获取更多 Pythonic 配置选项
添加到Erik Kalkoken 的答案。您也许可以编写一个转换器函数,它可以让您更好地控制如何评估该值。
def converter(in_str: str):
try:
out = literal_eval(in_str)
except Exception:
out = in_str
return out
parser = configparser.ConfigParser(converters={"any": lambda x: converter(x)})
value = parser.getany("section", "key")