Python: разобрать текстовый файл и показать как график - PullRequest
0 голосов
/ 03 мая 2011

У меня есть текстовые файлы в этом формате:

   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

То, что вы видите выше, это иерархия вызовов.

Отступы показывают, какие методы были вызваны или являются вызывающими.

Любые строки, начинающиеся с ':', показывают возвращаемое значение метода.

Моя проблема в том, как проанализировать текстовые файлы и представить это как дерево иерархии вызовов, где каждый узел является вызванным методом. Мы прикрепляем атрибуты к каждому узлу, которые являются аргументами, передаваемыми этому методу.

Ответы [ 2 ]

1 голос
/ 03 мая 2011

Вот мой выстрел в этом:

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
>>> 
1 голос
/ 03 мая 2011

Похоже, вам нужен настоящий парсер, поскольку это не тривиальный формат.

Существует множество методов написания синтаксических анализаторов на Python. См. Например, PLY . Другой - PyParsing .

В качестве альтернативы, может быть Python Call Graph - это то, что вам действительно нужно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...