2009-12-17 80 views
1

我有一个消息定义文件看起来像这样解析Python中的数据文件(2.5.2)

struct1 
{ 
    field="name" type="string" ignore="false"; 
    field="id" type="int" enums=" 0="val1" 1="val2" "; 
} 

struct2 
{ 
    field = "object" type="struct1"; 
    ... 
} 

我如何解析这个与键的struct1,struct2'字典和值应该是一个字典的列表,每个对应于相应的行号,这样我可以执行下列操作

dict['struct1'][0]['type'] // Would return 'string' 
dict['struct1'][1]['type'] // Would return 'int' 
dict['struct1'][1]['enums']['0'] // Would return 'val1' 
dict['struct2'][0]['type'] // Would return 'struct1' 

等..

另外,我可以改变定义文件并且如果格式你有修改定义文件格式的建议,以便于解析,请告诉我。

感谢

回答

2

我想简单地使用Python的消息定义文件格式。

让你的消息定义文件是一个普通的Python文件:

# file messages.py 
messages = dict(
    struct1=[ 
     dict(field="name", type="string", ignore=False), 
     dict(field="id", type="int", enums={0: "val1", 1: "val2"}), 
     ], 
    struct2=[ 
     dict(field="object", type="struct1"), 
     ] 
    ) 

您的程序可以然后导入并直接使用该数据结构:

# in your program 
from messages import messages 
print messages['struct1'][0]["type"] 
print messages['struct1'][1]['type'] 
print messages['struct1'][1]['enums'][0] 
print messages['struct2'][0]['type'] 

使用这种方法,你让Python的做为你解析。

而且你也获得了很多可能性。例如,想象一下(出于某种奇怪的原因)有一个包含1000个名为“field_N”的消息结构。使用传统的文件格式,你将不得不添加1000行的字段定义(除非你在你的配置文件解析器中建立了一些循环),然后你就可以创建编程语言了。使用Python为了这个目的,你可以这样做:

messages = dict(
    ... 
    strange_msg=[dict(field="field_%d" % i) for i in range(1000)], 
    ... 
    ) 

顺便说一句,关于Python 2.6,用代替字典命名为元组是一个选项。或者可以使用众多的“Bunch”类(请参阅Python Cookbook的2.5版的namedtuple)。

编辑:

下面是代码在命令行上所指定读取的消息定义文件。它使用execfile而不是import

# file mainprogram.py 

def read_messages_from_file(filename): 
    module_dict = {} 
    execfile(filename, module_dict) 
    return module_dict['messages'] 

if __name__ == "__main__": 
    from pprint import pprint 
    import sys 

    for arg in sys.argv[1:]: 
     messages = read_messages_from_file(arg) 
     pprint(messages) 

执行:

$ python mainprogram.py messages1 messages2 messages3 

将读取并打印在每个文件中定义的消息。

+0

如果我有3个单独的文件,我写的脚本时不知道其名称。我希望将文件的名称作为参数传入。这将如何完成? – randomThought 2009-12-17 15:40:53

+1

我可以看到这方面的优势,但感觉很糟糕,就像一个巨大的安全风险。或者让你的代码奇迹般地陷入困境。我不确定这是否合理。 – 2009-12-17 15:41:15

+2

如果你认为这是一个安全风险,你应该问自己的第一件事是:谁会将一些恶意代码添加到消息定义文件中。找到那个人并摆脱他。如果他存在,是什么阻止他编辑程序本身? – codeape 2009-12-17 15:57:10

4

使用可以使用json作为文件格式,它支持(在Python行话),字典和列表。由于JSON只支持Python的2.6和更高的是本地人,你需要这个库:http://pypi.python.org/pypi/simplejson/2.0.9

{ "struct1" 
    [ 
     {"field" : "name", "type" : "string", "ignore" : false }, 
     {"field" : "id", "type" : "int", "0" : "val1", "1" : "val2" } 
     {"field" : "id", "type" : "int", "enums" : { "0": "val1", "1": "val2"}} 
    ] 
    "struct2" 
    [ ... ] 
} 

蟒蛇部分(勾勒,未测试):

>>> import simplejson as json 
>>> d = json.loads(yourjsonstring) 
>>> d['struct1'][0]['field'] 
name 
>>> d['struct1'][2]['enums']['0'] 
val1 
... 
+0

我该如何编写嵌套字典部分?就像我想在第二行 – randomThought 2009-12-17 15:32:54

+0

第二行字典枚举我喜欢这个答案,所以upvote,但我发现我不能安装插件的生产环境,所以不能使用这种方法。 – randomThought 2009-12-17 20:32:47

4

使用YAML代替。 python有PyYAML库。它被Google AppEngine大量使用。

这仅仅是一个友善的建议:-)

实例(映射标器以序列):

american: 
    - Boston Red Sox 
    - Detroit Tigers 
    - New York Yankees 
national: 
    - New York Mets 
    - Chicago Cubs 
    - Atlanta Braves 

也有当然的JSON这对Python的支持,充裕的(但往往伤害了我手指多一点;-)

4

我可以推荐YAML?恕我直言,语法对于数据输入更具可读性,然后您不必编写和维护解析器。 Eschew XML - 对文本进行标记很好,但不适合数据输入,因为文本不是人类可读的,所有重复标签处处都是可读的。

+0

YAML中的上述2结构的文件格式是什么?你能提供一个例子吗? – randomThought 2009-12-17 15:33:42

+0

推迟到jldupont :-) – 2009-12-17 15:35:13

0

由于您可以随意更改文件格式,因此可以将其更改为Python库可读取和写入的几种格式中的任意一种格式。例如,JSON,YAML,XML甚至内置的ConfigParser

[struct1] 
field: name 
type: string 
ignore: false 
# etc.