https://github.com/protocolbuffers/protobuf/releases/tag/v3.6.1 여기서
protobuf-all-3.6.1.zip 다운로드하고
protoc-3.6.1-win32.zip 다운로드 한 다음에
튜토리얼 참고해서 example에 있는 addressbook.proto를 protoc로 컴파일하면 addressbook_pb2.py가 만들어진다.
단 이 때, 만들어진 addressbook_pb2.py를 사용하려면 protobuf 라이브러리가 필요함. serialization같은걸 처리해주는 함수가 여기에 있다.
```python
pip install protobuf
```
C++ 같은 언어도 마찬가지로 protoc로 컴파일하는데 인자를 다르게 주면 .cpp가 만들어진다.
* pickle 대비 장점은?
Python pickling is the default approach since it's built into the language, but it doesn't deal well with schema evolution, and also doesn't work very well if you need to share data with applications written in C++ or Java.
* json 대비 장점은?
Json은 human readable하다는게 장점.(텍스트 기반이니까.)
schema를 몰라도 사용할 수 있다는 것도 장점.
Web기반에서 쓸거면 이게 거의 베스트지.
Protobuf는 훨씬 compact하고 빠르다는게 장점.
그리고 정해진 schema가 있어서 이대로 직렬화/역직렬화 할 수 있어 타입이 안맞아 오류날 가능성이 적다는 것.
그래서 내부 서비스에서 사용하면 좋음.
여러 종류의 message를 사용해야 하는 경우 length가 필요하다.
Person과 SomeThing 두 가지 message가 있는 상황에서, Person을 파일에 저장한 후 SomeThing을 다시 파일에 저장. 그리고 이들을 다시 Person, SomeThing 순서로 읽어들일 때, 저장된 Person의 길이만큼만 먼저 읽어서 Person으로 파싱해야한다.
테스트는 그냥 File IO로 했지만, 소켓 프로그래밍 할 때 유의해야 함. 즉, protobuf를 사용하더라도 length를 먼저 보내주고 그 만큼만 읽도록 해야한다.
```python
person = addressbook_pb2.Person()
person.id = 1
person.name = "bob"
something = addressbook_pb2.SomeThing()
something.id = 3
something.name = "asdf"
# Write the new address book back to disk.
with open(sys.argv[1], "wb") as f:
length = f.write(person.SerializeToString())
f.write(something.SerializeToString())
get_person = addressbook_pb2.Person()
get_some = addressbook_pb2.SomeThing()
with open(sys.argv[1], "rb") as f:
get_person.ParseFromString(f.read(length))
get_some.ParseFromString(f.read())
print(get_person.id)
print(get_person.name)
print(get_some.id)
print(get_some.name)
```
```
λ python add_person.py aaa length를 안쓰는 경우. get_person에서 모조리 읽어버린다.
1
bob
0
λ python add_person.py aaa
1
bob
3
asdf
```
* 공홈 예제에 올라와있는건 AddressBook이라는 message만 이용했고, 여기서 `` repeated``를 이용해 여러 Person을 불러오도록 했다. 다중 메시지 처리는 이런 식으로 해야 함.
enum
enum은 반드시 0부터 시작해야 하고, 명시되지 않으면 default value인 0이 된다.
0인 경우 Serialize할 때 그냥 저장이 안되는듯? xxd로 찍어보면 2바이트가 축소된다. 그래서 print할 때 찍히지 않는 듯.