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
你看到的内容是一个调用层级结构。
缩进的部分表示哪些方法被调用了或者正在调用其他方法。
任何以':'开头的行表示一个方法的返回值。
我遇到的问题是如何解析这些文本文件,并把它们表示成一个调用层级树,每个节点都是一个被调用的方法。我们会给每个节点附加一些属性,这些属性就是传递给该方法的参数。
2 个回答
1
看起来你需要一个真正的解析器,因为这个格式并不简单。
在Python中,有很多方法可以编写解析器。比如说,你可以看看PLY。另一个选择是PyParsing。
另外,也许Python Call Graph才是你真正需要的呢?
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),]"]]]]]]
>>>
这是一个嵌套的结构,包含 [ 层级, 调用, 结果, 子调用 ]
,其中子调用的结构和它们的父调用是一样的。
格式化的一种方式是:
>>> 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
>>>