2015-08-28 21 views
1

我需要解析包含應用程序配置的文本文件。文件內容的格式如下:以遞歸方式處理文本的Python方法

參數1 = VAL1
參數2 =值2
hash.param3 = {
subparam3 = subval3
subparam4 = subval4
}
...

我想將它存儲在字典中:

self.values = {'param1': 'value1', 'param2': 'value2', 
       'param3':{'subparam3':'subvalue3', 'subparam4': 'subvalue4'} 

我有這個工作正常使用全局變量之間共享的一些功能,但想再次嘗試使用類作爲學習練習,我已經做了,但它仍然感覺笨重。

這是我目前有:

class Cfg(object): 
    def __init__(self, abs_path): 
     self._text = iter(open(abs_path, 'r').readlines()) 
     self.values = {} 
     self._parse_cfg(self.values) 

    @property 
    def next_line(self): 
     """Get next non-blank, non-comment line.""" 
     while True: 
      nl = next(self._text).strip() 
      if nl and not nl.startswith('#'): 
       return nl 

    def _parse_cfg(self, dic): 
     while True: 
      try: 
       line = self.next_line 
       # closing brace signals end of sub dict 
       if line.startswith('}'): 
        break 
       # Look for param with hash prefix, which signifies a new subdict 
       elif re.match(hash_rgx, line): 
        m = re.match(hash_rgx, line) 
        # Add new hash dict 
        dic[m.group('hash')] = {} 
        # collect keys/values for subdict until closing brace found 
        self._parse_cfg(dic[m.group('hash')]) 

       # Look for normal key=value pair 
       elif re.match(val_rgx, line): 
        m = re.match(val_rgx, line) 
        dic[m.group('key')] = m.group('val') 
       else: 
        raise ValueError('line ignored *' + str(line) + '*') 
      except StopIteration: 
         break 

我正在尋找如何做到這一點在一個更清潔,更Python的方式提出建議。

謝謝!

+0

看起來像這屬於http://codereview.stackexchange.com –

+0

遞歸不是pythonic。 http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html – saarrrr

+0

當next_line(self)方法到達輸入結尾時,它會做什麼? –

回答

0

如果你有配置文件的控制權,那麼最好使用更多的編程友好數據格式,比如json,yaml(甚至是xml)。

否則,將它轉換成json,如果可能的話,也許用':'替換'='(如果這很簡單)。在這種情況下,您可以輕鬆地使用json.loads

import json 
json.loads(configuration_string) 
0

您可以創建一個遞歸調用自己,當它遇到開括號的功能。下面的代碼將返回您想要的示例數據。

data="""param1=val1 
param2=val2 
param3={ 
subparam3=subval3 
subparam4=subval4 
} 
""" 

# given a string of configuration data separated by newlines, put it into a dictionary 
def dict_from_data(data): 
    newdict = {} 
    datalist=data.splitlines() 
    # create iterable here so that we can skip lines if we encounter a brace {} section 
    iterable = iter(range(len(datalist))) 
    for num in iterable: 
     skiplines=0 
     key,val = datalist[num].split('=') 
     if val == '{': 
      # find the matching close brace. This won't work for nested braces, but could be adapted. 
      ix = num + 1 
      while skiplines==0: 
       if datalist[ix][0] == '}': 
        skiplines = ix-num 
       ix +=1 
      # call this function recursively with the lines inside the brace, 
      val = dict_from_data('\n'.join([datalist[n] for n in range(num+1, num+skiplines)])) 
      # and then skip those lines at this recursion depth. 
      for i in range(skiplines): 
       iterable.next() 
     newdict[key]=val 
    return newdict 

values = dict_from_data(data) 
print "Result of data parsing:" 
print values