将 ConfigParser 值转换为 python 数据类型

问题描述 投票:0回答:6

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 eval configparser
6个回答
16
投票

如果您使用的是 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

5
投票

这是另一种解决方案。您可以生成一个

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")
# ...

4
投票

对于那些可能正在寻找另一个更简单的答案的人,您可以使用 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 之上的包装器,因此完全兼容。

查看https://pypi.python.org/pypi/localconfig


1
投票

如果您使用的是 2.7+,则可以使用

.getint
.getfloat
.getbool
方法。您可以在 docs

中了解有关它们的更多信息

因此您的应用程序将使用

print cp.getint('one', 'key')


0
投票

查看 ConfigIt 以获取更多 Pythonic 配置选项

https://github.com/barberj/ConfigIt


0
投票

添加到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")
© www.soinside.com 2019 - 2024. All rights reserved.