2009-12-17 2 views
1

는 내가 키 'struct1, struct2'와 사전에이 구문을 분석 할 수 있고 값이 될 방법이파이썬에서 데이터 파일을 구문 분석 (2.5.2)

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

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

과 같은 메시지 정의 파일이 제가

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' 

등등 .. 또한

따라, I는 정의 파일 및 만약 포맷 변경을 할 수 있도록 사전 목록 각각은 각각의 행 번호에 대응 y는 구문 분석을 쉽게하기 위해 정의 파일 형식을 수정하는 것에 대한 제안 사항이 있으니 알려주십시오.

답변

2

나는 단순히 메시지 정의 파일 형식 파이썬을 사용합니다.

메시지 정의 파일이 일반 파이썬 파일하자 :

# 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'] 

를, 파이썬은을하자 당신을 위해 파싱.

당신은 또한 많은 가능성을 얻습니다. 예를 들어, (이상한 이유로) 여러분이 "field_N"이라는 1000 개의 필드를 가진 메시지 구조를 가지고 있다고 상상해보십시오. 기존 파일 형식을 사용하면 1000 줄의 필드 정의를 추가해야합니다 (구성 파일 파서에 루핑을 작성하지 않는 한 - 어쨌든 프로그래밍 언어를 만드는 중입니다). 이 목적을 위해 파이썬을 사용하면 같은 뭔가를 할 수 : 대신 DICT의 이름 튜플을 사용하여, 파이썬 2.6,

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

BTW하는 것은 옵션입니다. 또는 여러 개의 "Bunch"클래스를 사용할 수 있습니다 (2.5의 namedtuple은 Python 요리 책을 참조하십시오).

편집 : 명령 행에 지정된 메시지 정의 파일을 읽어

다음

입니다 코드입니다. import 대신 execfile을 사용합니다.

# 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

+1

나는이 점에서 이점을 볼 수 있지만 엄청난 보안 위험처럼 느껴진다. 또는 코드가 마술처럼 엉망이 될 수도 있습니다. 비록 그것이 의미가 있는지 나는 잘 모르겠다. –

+2

이것이 보안 위험이라고 생각하는 경우 가장 먼저해야 할 일은 다음과 같습니다. 메시지 정의 파일에 악성 코드를 추가 할 사람은 누구입니까? 그 남자를 찾아서 제거하십시오. 그리고 그가 존재한다면, 그로 하여금 프로그램 자체를 편집하지 못하게 막고있는 것은 무엇입니까? – codeape

4

을 사용하여 파일 형식으로 json 사용할 수 있습니다

덕분에, 그것은 사전 및 목록 (파이썬 용어로)를 지원합니다. 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

중첩 된 사전 파트는 어떻게 작성합니까? 마찬가지로 내가 두 번째 줄에 사전으로 enum을 원한다. – randomThought

+0

나는이 대답을 좋아해서 upvote하지만 프로덕션 환경에서 플러그인을 설치할 수 없다는 것을 알았으므로이 방법을 사용할 수 없었다. – randomThought

4

사용 YAML 대신 JSON 지원은 파이썬 2.6 이상에서 기본이기 때문에, 당신은이 라이브러리가 필요합니다. Python 용 PyYAML 라이브러리가 있습니다. Google AppEngine에서 많이 사용됩니다.

예 :-) 단지 친절한 제안 (시퀀스에 매핑 스칼라)입니다 : 파이썬에 대한 충분한 지원을하고있다 (그러나 상처를하는 경향이 물론 JSON이

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

내 손가락 좀 더 ;-)

4

나는 YAML을 추천 할까? IMHO 구문은 데이터 입력을 위해 더 읽기 쉽고 파서를 작성하고 유지할 필요가 없습니다. Eschew XML - 텍스트를 마크 업하는 데는 좋지만 데이터가 사람이 읽을 수있는 텍스트가 아니기 때문에 데이터 입력에 좋지는 않습니다.

+0

위의 2 구조체에 대한 YAML의 파일 형식은 무엇이겠습니까? 예제를 제공해 줄 수 있습니까? – randomThought

+0

jldupont :-)로 보냄 –

0

파일 형식을 자유롭게 변경할 수 있으므로이 파일 형식을 읽고 쓸 수있는 파이썬 라이브러리가있는 여러 형식 중 하나로 변경할 수 있습니다. 예를 들어, JSON, YAML, XML 또는 심지어 내장 된 ConfigParser.

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