2011-03-22 53 views
0

因此,我最近開始爲我正在開發的Python項目編寫配置解析器。我最初避免configparser和configobj,因爲我想支持一個配置文件,如下所示:Python配置解析器(重複密鑰支持)

key=value 
key2=anothervalue 

food=burger 
food=hotdog 
food=cake icecream 

總之,這個配置文件將被通過命令行通過SSH經常編輯。所以我不想挑選或挑剔間距(如YAML),但我也希望避免具有多個值(容易10或更多)的密鑰在vi中進行換行。這就是爲什麼我想支持重複鍵。當我向Python配置對象尋求食物時,它會給我一個帶有'漢堡','熱狗','蛋糕','冰淇淋'的列表。如果沒有定義食物價值,它會查找一個默認配置文件,並給我那個/那些值。

我已經執行上述

然而,我的煩惱時,我意識到,我想支持維護在線評論和這樣的開始。處理讀寫配置文件的方式是將文件解碼爲內存中的字典,從字典中讀取值或將值寫入字典,然後將該字典轉儲迴文件中。這對於保持線路順序和評論等並不是很好,而且它也在扼殺我。

A)ConfigObj看起來像它有我需要的一切,除了支持重複鍵。相反,它要我做一個列表將是一個痛苦,因爲線包裝在ssh上通過vi手動編輯。我可以讓configobj更友好的ssh/vi嗎?

B)我的自制解決方案是否錯誤?有沒有更好的方式來讀/寫/存儲我的配置值?是否有任何簡單的方法可以通過修改該行並從內存中重寫整個配置文件來處理更改配置文件中的鍵值?

回答

0

瘋狂的想法:將你的字典值作爲一個3元組的列表,包括行號,列號和值本身,並添加特殊的註釋鍵。

CommentSymbol = ';' 
def readConfig(filename): 
    f = open(filename, 'r') 
    if not f: 
     return 
    def addValue(dict, key, lineIdx, colIdx, value): 
     if key in dict: 
      dict[key].append((lineIdx, colIdx, value)) 
     else: 
      dict[key] = [(lineIdx, colIdx, value)] 
    res = {} 
    i = 0 
    for line in f.readlines(): 
     idx = line.find(CommentSymbol) 
     if idx != -1: 
      comment = line[idx + 1:] 
      addValue(res, CommentSymbol, i, idx, comment) 
      line = line[:idx] 
     pair = [x.strip() for x in line.split('=')][:2] 
     if len(pair) == 2: 
      addValue(res, pair[0], i, 0, pair[1]) 
     i += 1 
    return res 

def writeConfig(dict, filename): 
    f = open(filename, 'w') 
    if not f: 
     return 
    index = sorted(dict.iteritems(), cmp = lambda x, y: cmp(x[1][:2], y[1][:2])) 
    i = 0 
    for k, V in index: 
     for v in V: 
      if v[0] > i: 
       f.write('\n' * (v[0] - i - 1)) 
      if k == CommentSymbol: 
       f.write('{0}{1}'.format(CommentSymbol, str(v[2]))) 
      else: 
       f.write('{0} = {1}'.format(str(k), str(v[2]))) 
      i = v[0] 
    f.close() 
+0

,你需要其他功能增值字典 – Andrey 2011-03-22 19:34:04

0

那麼我會盡量利用標準庫中的內容,如果我可以的話。

爲配置解析器類的簽名是這樣的:

class ConfigParser.SafeConfigParser([defaults[, dict_type[, allow_no_value]]])

通知的dict_type說法。提供時,將用於爲部分列表,部分內的選項以及默認值構造字典對象。它默認爲collections.OrderedDict。也許你可以通過一些東西來獲得你想要的多鍵行爲,然後獲得ConfigParser的所有優點。您可能必須編寫自己的類才能執行此操作,或者您可能會在PyPi或ActiveState配方中找到爲您編寫的類。嘗試尋找一個包或multiset類。

我想無論是走這條路還是隻吸起來,並做一個清單:

foo = value1, value2, value3 
+1

我嘗試和失敗,主要是因爲該方法_read RawConfigParser使用相同的字典來分析多行值,將它們作爲密鑰的映射對象寫入列表中。並且最後再做一次傳遞以加入字典中的所有內容。所以你最終會得到類似'{'key':['value'],'key':'value'}',並且需要非常糟糕的黑客才能使其工作。 – 2014-12-30 14:11:40