2012-12-06 38 views
3

使用ConfigParserjson從Python配置文件中讀取條件的最佳方式是什麼?我想讀的東西,如:從配置文件讀取布爾條件?

[mysettings] 
x >= 10 
y < 5 

,然後把它應用到xy定義變量的代碼,條件將被應用爲的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這樣的條件。

必須有更好的方法,但是想法是使用配置文件中的簡單布爾表達式約束變量的值。

+1

這與JSON有什麼關係? –

+0

json可用於解析Python eval'able結構 – user248237dfsf

+1

是的,但您顯示的配置格式不是JSON。 –

回答

5

我不認爲你想,或者需要同時使用configparserjson,因爲它們本身都是足夠的。以下是如何與每一個做到這一點:

假設您有一個配置文件從相信,包含像這樣來源:

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)) 
+0

+1解決這個問題的好方法。 – neil

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) 

結果:

​​

或者,更貼近您的例子:

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} 
+0

雖然我想從文本文件中讀取表達式,其中包含其他設置,但不是來自'.py'文件。它可以適應嗎? – user248237dfsf

+0

@ user248237那麼,爲什麼不把這些其他設置存儲在'config.py'中呢?當然,你可以做整個'read()' - >'eval()'舞蹈,但是爲什麼還要這樣呢?如果你實際上有一個你不能改變的現有配置文件(格式),你將不得不存儲文字Python表達式,最後是'eval()'它們。 –

+0

@ user248237那麼可以將配置文件視爲受信任的輸入嗎? –