Python将C头文件转换为字典
我有一个C语言的头文件,里面包含了一系列的类。我想写一个函数,把这些类转换成Python的字典。下面是这个文件的一个示例。
格式大概是这样的:
class CFGFunctions {
class ABC {
class AA {
file = "abc/aa/functions"
class myFuncName{ recompile = 1; };
};
class BB
{
file = "abc/bb/functions"
class funcName{
recompile=1;
}
}
};
};
我希望能把它变成这样:
{CFGFunctions:{ABC:{AA:"myFuncName"}, BB:...}}
# Or
{CFGFunctions:{ABC:{AA:{myFuncName:"string or list or something"}, BB:...}}}
最后,我想得到一个文件路径字符串(其实是一个文件夹的路径……不过无所谓),还有与这个文件/文件夹路径在同一个类里的类名。
我在StackOverflow和谷歌上查过,但大多数找到的内容都是关于把行分割成字典,而不是处理多层的“块”。
我知道我需要遍历这个文件,但我不太确定最有效的方式来转换成字典。我在想,我需要抓取外层的类和它相关的括号,然后对里面剩下的文本做同样的处理。
如果这些说的不太清楚,那是因为我自己也还没完全搞明白这个过程,哈哈。
如果需要更多信息,我很乐意提供。
下面的代码是我大概想的一个快速示例……它很可能是坏的,也可能不工作,但这就是我想到的过程。
def get_data():
fh = open('CFGFunctions.h', 'r')
data = {} # will contain final data model
# would probably refactor some of this into a function to allow better looping
start = "" # starting class name
brackets = 0 # number of brackets
text= "" # temp storage for lines inside block while looping
for line in fh:
# find the class (start
mt = re.match(r'Class ([\w_]+) {', line)
if mt:
if start == "":
start = mt.group(1)
else:
# once we have the first class, find all other open brackets
mt = re.match(r'{', line)
if mt:
# and inc our counter
brackets += 1
mt2 = re.match(r'}', line)
if mt2:
# find the close, and decrement
brackets -= 1
# if we are back to the initial block, break out of the loop
if brackets == 0:
break
text += line
data[start] = {'tempText': text}
====
示例文件
class CfgFunctions {
class ABC {
class Control {
file = "abc\abc_sys_1\Modules\functions";
class assignTracker {
description = "";
recompile = 1;
};
class modulePlaceMarker {
description = "";
recompile = 1;
};
};
class Devices
{
file = "abc\abc_sys_1\devices\functions";
class registerDevice { recompile = 1; };
class getDeviceSettings { recompile = 1; };
class openDevice { recompile = 1; };
};
};
};
编辑:如果可能的话,如果我必须使用一个包,我希望它在程序的目录下,而不是在一般的Python库目录下。
1 个回答
正如你所发现的,解析是进行转换所必需的。可以看看PyParsing这个库,它是一个相对简单易用的库,可以在你的Python程序中实现解析。
补充说明:这只是一个非常简化的版本,用来识别一个非常简单的语法,类似于问题开头的例子。虽然这个代码不能直接工作,但可能会给你指明方向:
from pyparsing import ZeroOrMore, OneOrMore, \
Keyword, Literal
test_code = """
class CFGFunctions {
class ABC {
class AA {
file = "abc/aa/functions"
class myFuncName{ recompile = 1; };
};
class BB
{
file = "abc/bb/functions"
class funcName{
recompile=1;
}
}
};
};
"""
class_tkn = Keyword('class')
lbrace_tkn = Literal('{')
rbrace_tkn = Literal('}')
semicolon_tkn = Keyword(';')
assign_tkn = Keyword(';')
class_block = ( class_tkn + identifier + lbrace_tkn + \
OneOrMore(class_block | ZeroOrMore(assignment)) + \
rbrace_tkn + semicolon_tkn \
)
def test_parser(test):
try:
results = class_block.parseString(test)
print test, ' -> ', results
except ParseException, s:
print "Syntax error:", s
def main():
test_parser(test_code)
return 0
if __name__ == '__main__':
main()
另外,这段代码只是解析器 - 它并不会生成任何输出。正如你在PyParsing的文档中看到的,你可以在后面添加你想要的操作。但第一步是识别你想要翻译的内容。
最后一点:不要低估解析代码的复杂性……即使有像PyParsing这样的库来处理大部分工作,仍然有很多方法可能让你陷入无限循环和其他解析的麻烦中。要一步一步地实现功能!
补充:关于PyParsing的一些信息来源有:
http://werc.engr.uaf.edu/~ken/doc/python-pyparsing/HowToUsePyparsing.html
http://pyparsing.wikispaces.com/
特别有趣的是http://pyparsing.wikispaces.com/Publications,里面有很多文章 - 其中有几篇是关于PyParsing的入门介绍。
http://pypi.python.org/pypi/pyparsing_helper是一个用于调试解析器的图形界面工具。
在stackoverflow上还有一个'Pyparsing'标签,PyParsing的作者Paul McGuire似乎经常在那儿出现。
* 注意: *来自PaulMcG的评论:Pyparsing不再托管在wikispaces.com上。请访问github.com/pyparsing/pyparsing