使用ConfigParser
和json
从Python中的配置文件中读取条件的最佳方法是什么?我想阅读类似的内容:
[mysettings]
x >= 10
y < 5
然后将其应用于x
和y
定义变量的代码,并且条件将应用于代码中x, y
的值。类似的东西:
l = get_lambda(settings["mysettings"][0])
if l(x):
# do something
pass
l2 = get_lambda(settings["mysettings"][1])
if l2(y):
# do something
pass
理想情况下,我也想指定x + y >= 6
等条件。
必须有更好的方法,但想法是使用配置文件中的简单布尔表达式来约束变量的值。
答案 0 :(得分:5)
这是一个使用Python本身作为描述配置文件的语言的例子:
<强> config.py 强>
mysettings = [
lambda x: x >= 10,
lambda y: y < 5,
]
<强> main.py 强>
from config import mysettings
a = 42
b = 300
for i, condition in enumerate(mysettings):
for value in (a, b):
result = condition(value)
print "condition %s for value %s is: %s" % (i, value, result)
<强>输出:强>
condition 0 for value 42 is: True
condition 0 for value 300 is: True
condition 1 for value 42 is: False
condition 1 for value 300 is: False
这当然假设配置文件被认为是可信输入,因为通过执行condition(value)
,您将执行配置文件中定义的任何功能。
但是,无论您使用何种语言,我都没有看到任何方法:条件为expressions,因此可执行代码。如果你想得到一个你可以在你的代码中使用的Python表达式,那么你迟早要评估那个表达式。
修改强>
如果由于某种原因你真的不能使用Python,那么你可以用JSON中的配置文件来实现它:
<强> config.json 强>
{
"mysettings": {
"color": "Blue",
"expressions": [
"x >= 10",
"y < 5"
]
},
"other_settings": {
"color": "red"
}
}
<强> main.py 强>
import json
x = 42
y = 300
def eval_expr(expr, values):
result = eval(expr, values.copy())
print "The expression '%s' evaluates to '%s' for the values %r" % (
expr, result, values)
return result
f = open('config.json')
data = json.loads(f.read())
settings = data["mysettings"]
for expr in settings['expressions']:
values = dict(x=x, y=y)
eval_expr(expr, values)
结果:
The expression 'x >= 10' evaluates to 'True' for the values {'y': 300, 'x': 42}
The expression 'y < 5' evaluates to 'False' for the values {'y': 300, 'x': 42}
或者,更接近你的例子:
x = 1
y = 2
values = dict(x=x, y=y)
e1 = settings['expressions'][0]
if eval_expr(e1, values):
# do something
pass
e2 = settings['expressions'][1]
if eval_expr(e2, values):
# do something else
pass
结果:
The expression 'x >= 10' evaluates to 'False' for the values {'y': 2, 'x': 1}
The expression 'y < 5' evaluates to 'True' for the values {'y': 2, 'x': 1}
答案 1 :(得分:5)
我认为您不想或不需要同时使用configparser
和 json
,因为两者本身就足够了。以下是每种方法的使用方法:
假设您有来自可信源的配置文件,其中包含以下内容:
<强> myconfig.ini
强>
[mysettings]
other=stuff
conds=
x >= 10
y < 5
x + y >= 6
它可以像这样解析和使用:
from __future__ import print_function
try:
import configparser
except ImportError: # Python 2
import ConfigParser as configparser
get_lambda = lambda expr: lambda **kwargs: bool(eval(expr, kwargs))
cp = configparser.ConfigParser()
cp.read('myconfig.ini')
exprs = cp.get('mysettings', 'conds').strip()
conds = [expr for expr in exprs.split('\n')]
l = get_lambda(conds[0])
l2 = get_lambda(conds[1])
l3 = get_lambda(conds[2])
def formatted(l, c, **d):
return '{:^14} : {:>10} -> {}'.format(
', '.join('{} = {}'.format(var, val) for var, val in sorted(d.items())), c, l(**d))
l = get_lambda(conds[0])
print('l(x=42): {}'.format(l(x=42)))
print()
print(formatted(l, conds[0], x=42))
print(formatted(l2, conds[1], y=6))
print(formatted(l3, conds[2], x=3, y=4))
这会产生以下输出:
l(x=42): True
x = 42 : x >= 10 -> True
y = 6 : y < 5 -> False
x = 3, y = 4 : x + y >= 6 -> True
如果信息保存在类似于此的JSON格式文件中:
<强> myconfig.json
强>
{
"mysettings": {
"other": "stuff",
"conds": [
"x >= 10",
"y < 5",
"x + y >= 6"
]
}
}
可以使用json
模块轻松解析它,并以类似的方式使用:
import json
with open('myconfig.json') as file:
settings = json.loads(file.read())
conds = settings['mysettings']['conds']
......剩余部分将是相同的并产生相同的结果。即:
l = get_lambda(conds[0])
print('l(x=42): {}'.format(l(x=42)))
print()
print(formatted(l, conds[0], x=42))
print(formatted(l2, conds[1], y=6))
print(formatted(l3, conds[2], x=3, y=4))