我有一个C头文件,其中包含一系列类,并且我正在尝试编写一个将这些类转换为python dict的函数。该文件的示例位于底部。
格式将类似于
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:...}}}
最后,我的目标是获取文件路径字符串(实际上是文件夹的路径...,但无论如何),并且类名称与文件/文件夹路径在同一类中。
我看过SO,Google等,但是我发现的大多数事情都是关于将行拆分为dict,而不是n深度的“块”
我知道我将不得不遍历该文件,但是,我不确定将其转换为dict的最有效方法。
我在想我需要抓住外部类及其相关的括号,然后对保留在内部的文本进行相同的处理。
如果这些都没有道理,那是因为我自己对这个过程还不太了解哈哈
如果需要更多信息,我们很乐意提供。
以下代码是我正在思考的快速模型...
它很可能已损坏,可能无法正常工作。但是我正在考虑的过程
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 libs目录中。
最佳答案
正如您检测到的那样,解析是进行转换所必需的。看一下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是用于调试解析器的GUI
在stackoverflow上还有一个“标记” Pyparsing,Paul McGuire(PyParsing的作者)似乎经常来此。
* 注意: *
来自PaulMcG的以下评论:Pyparsing不再托管在wikispaces.com上。转到github.com/pyparsing/pyparsing
关于python - Python将C头文件转换为字典,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25026932/