니삼 블로그
Protobuf python 본문
Protobuf로 통신하는 애플리케이션을 분석 할 일이 생겼다. 분석에 앞서 Protobuf를 먼저 사용해보려고 한다.
Protocol Buffers는 구글에서 개발한 데이터 교환 포맷이다. 그냥 데이터 직렬화 도구이다. 자세한 내용은 깃허브에서 확인하자.
Protobuf는 다양한 언어를 지원하고 있지만 python으로 진행하였다.
설치(apt-get)
# apt-get install protobuf-compiler $ protoc --version libprotoc 2.5.0 $sudo pip install protobuf |
설치가 끝났으면 직렬화할 데이터 포맷을 정의할 proto파일을 만들어야한다.
샘플 - addressbook.proto
package tutorial; message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; } message AddressBook { repeated Person person = 1; } |
proto의 포맷은 링크에서 자세히 볼 수 있다.
proto 파일을 빌드한다.
protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/addressbook.proto |
python_out 옵션을 통해서 파이썬에서 사용할 수 있는 클래스로 바꿔준다. 성공적으로 빌드가 되었다면 addressbook_pb2.py가 생성 된다.
작성했던 addressbook.proto 포맷을 이용하여 데이터를 직렬화 해보겠다.
빌드해서 생성된 addressbook_pb2를 import하고 이를 이용하여 데이터를 파일로 생성하는 예제이다.
write_adrress.py
#! /usr/bin/python import addressbook_pb2 import sys # This function fills in a Person message based on user input. def PromptForAddress(person): person.id = int(raw_input("Enter person ID number: ")) person.name = raw_input("Enter name: ") email = raw_input("Enter email address (blank for none): ") if email != "": person.email = email while True: number = raw_input("Enter a phone number (or leave blank to finish): ") if number == "": break phone_number = person.phone.add() phone_number.number = number type = raw_input("Is this a mobile, home, or work phone? ") if type == "mobile": phone_number.type = addressbook_pb2.Person.MOBILE elif type == "home": phone_number.type = addressbook_pb2.Person.HOME elif type == "work": phone_number.type = addressbook_pb2.Person.WORK else: print "Unknown phone type; leaving as default value." # Main procedure: Reads the entire address book from a file, # adds one person based on user input, then writes it back out to the same # file. if len(sys.argv) != 2: print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE" sys.exit(-1) address_book = addressbook_pb2.AddressBook() # Read the existing address book. try: f = open(sys.argv[1], "rb") address_book.ParseFromString(f.read()) f.close() except IOError: print sys.argv[1] + ": Could not open file. Creating a new one." # Add an address. PromptForAddress(address_book.person.add()) # Write the new address book back to disk. f = open(sys.argv[1], "wb") f.write(address_book.SerializeToString()) f.close() |
write로 생성된 raw데이터를 데이터를 읽는 예제이다.
read_address.py
#! /usr/bin/python import addressbook_pb2 import sys # Iterates though all people in the AddressBook and prints info about them. def ListPeople(address_book): for person in address_book.person: print "Person ID:", person.id print " Name:", person.name if person.HasField('email'): print " E-mail address:", person.email for phone_number in person.phone: if phone_number.type == addressbook_pb2.Person.MOBILE: print " Mobile phone #: ", elif phone_number.type == addressbook_pb2.Person.HOME: print " Home phone #: ", elif phone_number.type == addressbook_pb2.Person.WORK: print " Work phone #: ", print phone_number.number # Main procedure: Reads the entire address book from a file and prints all # the information inside. if len(sys.argv) != 2: print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE" sys.exit(-1) address_book = addressbook_pb2.AddressBook() # Read the existing address book. f = open(sys.argv[1], "rb") address_book.ParseFromString(f.read()) f.close() ListPeople(address_book) |
예제 코드를 실행하면 내가 작성했던 정보들을 읽을 수 있다.
끝