2011-05-03 65 views
0

我有一個在這個格式的文本文件:的Python:解析文本文件,並顯示爲圖形

BFrame.make() 
     Frame.make_bbox() 
     BBox.__init__(arg1=x, arg2=y, arg3=z) 
     : None 
     BBox.make() 
      BBox.chk_pre() 
      : None 
     : (1,1,2,2) 
     : None 
     ExConfig.__init__(filename=None) 
     ExConfig.setParam() 
      ExConfig.setfromKey(AUTO=[0.0, 0.0]) 
       ExConfig.setFromList([('PHOT', [2.5, 3.5]), ('BV', [0.0, 0.0])]) 
       : None 
      : None 
     : [returns a list of paramaters] 
     ExConfig.getKwList() 
      : [('A_THR', 3.0), ('B_THICK', 24),] 
     : None 
    etc.. 
    :Frame 

什麼你在上面看到的是一個調用層次。

縮進顯示哪些方法已被調用或正在調用。

任何以':'開頭的行都會顯示方法的返回值。

我的問題是如何解析文本文件,並將其表示爲調用層次樹,其中每個節點都是調用的方法。我們將屬性附加到每個節點,這些是傳遞給該方法的參數。

回答

1

看起來你需要一個真正的解析器,因爲這不是一個簡單的格式。

存在許多用於在Python中編寫解析器的方法。例如參見PLY。另一個是PyParsing

或者,也許Python Call Graph是你真正需要的嗎?

+0

類似的東西來pyCallGraph但對於具體的類/方法。我們的日誌記錄是在運行時完成的,因此稱爲方法被記錄。 – bnc110 2011-05-03 09:29:23

1

這裏是我拍這個:

a = """BFrame.make() 
     Frame.make_bbox() 
     BBox.__init__(arg1=x, arg2=y, arg3=z) 
     : None 
     BBox.make() 
      BBox.chk_pre() 
      : None 
     : (1,1,2,2) 
     : None 
     ExConfig.__init__(filename=None) 
     ExConfig.setParam() 
      ExConfig.setfromKey(AUTO=[0.0, 0.0]) 
       ExConfig.setFromList([('PHOT', [2.5, 3.5]), ('BV', [0.0, 0.0])]) 
       : None 
      : None 
     : [returns a list of paramaters] 
     ExConfig.getKwList() 
      : [('A_THR', 3.0), ('B_THICK', 24),] 
     : None 
    :Frame""" 

b = [ line.strip() for line in a.split("\n") ] 

stck1 = [] 
stck2 = [] 

while b: 
    add_v = b.pop(0) 
    if add_v[0] != ':': 
     stck1.append(add_v) 
    else: 
     if stck2: 
      mx = max([x[0] for x in stck2]) 
     else: 
      mx = 0 
     if len(stck1) < mx: 
      calls = [] 
      while stck2 and stck2[-1][0] == mx:    
       calls.append(stck2.pop()) 
      stck2.append([len(stck1), stck1.pop(), add_v, calls[::-1]]) 
     else: 
      stck2.append([len(stck1), stck1.pop(), add_v]) 

它給你這樣的:

>>> pprint.pprint(stck2, width=5) 
[[1, 
    'BFrame.make()', 
    ':Frame', 
    [[2, 
    'Frame.make_bbox()', 
    ': None', 
    [[3, 
     'BBox.__init__(arg1=x, arg2=y, arg3=z)', 
     ': None'], 
    [3, 
     'BBox.make()', 
     ': (1,1,2,2)', 
     [[4, 
     'BBox.chk_pre()', 
     ': None']]]]], 
    [2, 
    'ExConfig.__init__(filename=None)', 
    ': None', 
    [[3, 
     'ExConfig.setParam()', 
     ': [returns a list of paramaters]', 
     [[4, 
     'ExConfig.setfromKey(AUTO=[0.0, 0.0])', 
     ': None', 
     [[5, 
      "ExConfig.setFromList([('PHOT', [2.5, 3.5]), ('BV', [0.0, 0.0])])", 
      ': None']]]]], 
    [3, 
     'ExConfig.getKwList()', 
     ": [('A_THR', 3.0), ('B_THICK', 24),]"]]]]]] 
>>> 

嵌套[ hierarchy_level, call, result, children_calls ],使孩子們的結構相同,他們的父母。

一個辦法格式:

>>> def pretty(X): 
...  if len(X)==4: 
...   print '\t'*X[0], X[1], 'returns', X[2] 
...   print '\t'*X[0], 'children:' 
...   for child in X[3]: 
...    pretty(child) 
...  else: 
...   print '\t'*X[0], X[1], 'returns', X[2] 
...   print '\t'*X[0], 'no children' 
... 
>>> pretty(stck2[0]) 
    BFrame.make() returns :Frame 
    children: 
     Frame.make_bbox() returns : None 
     children: 
      BBox.__init__(arg1=x, arg2=y, arg3=z) returns : None 
      no children 
      BBox.make() returns : (1,1,2,2) 
      children: 
       BBox.chk_pre() returns : None 
       no children 
     ExConfig.__init__(filename=None) returns : None 
     children: 
      ExConfig.setParam() returns : [returns a list of paramaters] 
      children: 
       ExConfig.setfromKey(AUTO=[0.0, 0.0]) returns : None 
       children: 
        ExConfig.setFromList([('PHOT', [2.5, 3.5]), ('BV', [0.0, 0.0])]) returns : None 
        no children 
      ExConfig.getKwList() returns : [('A_THR', 3.0), ('B_THICK', 24),] 
      no children 
>>>