2009-12-17 45 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.