關於Protocol Buffers
Protocol Buffers是Google開發的用於序列化數據的機制,它無關開發語言,無關使用平臺,且具備良好的可擴展性。
使用Protocol Buffers,你只須要把你的數據定義爲結構化的protocol buffer數據,而後使用編譯工具把它編譯成特定語言下的代碼,調用編譯後的代碼接口,你就能很方便地將你的結構數據寫成數據流(編碼),或是將數據流讀取爲你的結構數據(解碼)。
目前Protocol buffers可支持的生成語言有Java,Python, Object-c, 以及C++, proto3版本還新增了Dart,Go, Ruby, C#。
html
編譯工具安裝
這裏說的編譯工具是指編譯.proto文件,即protocol compiler(protoc)
首先,安裝並選擇默認python版本:
python
sudo apt-get install python//系統自帶的python腳本,18.04上自帶版本仍然是2.7.15~rc1-1) //https://www.runoob.com/python3/python3-install.html 安裝python3 //使用update-alternatives修改系統默認配置python使用python3 update-alternatives --list python//列出全部可用的python版本 #/usr/bin/python2.7 #/usr/bin/python3.6 sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1 sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 2 //將python3.6優先級設爲2,就會自動設置爲默認python版本 python --version #Python 3.6.9 update-alternatives --config python//也能夠經過此命令修改默認python版本 有 2 個候選項可用於替換 python (提供 /usr/bin/python)。 選擇 路徑 優先級 狀態 ------------------------------------------------------------ * 0 /usr/bin/python3.6 2 自動模式 1 /usr/bin/python2.7 1 手動模式 2 /usr/bin/python3.6 2 手動模式 要維持當前值[*]請按<回車鍵>,或者鍵入選擇的編號:
再者,有了python,經過pip來安裝protobuf,protoclinux
sudo apt install python-pip//如未安裝,先安裝pip pip install protobuf grpcio-tools
protoc是用C++語言編寫的,若是你使用的是C++語言,能夠參考C++安裝說明來安裝protoc
非C++語言也能夠參考protobuf來安裝
git
Nanopb
Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is especially suitable for use in microcontrollers, but fits any memory restricted system.github
使用nanopb庫編譯.proto文件和工程使用,只須要下面兩步便可:ubuntu
- 使用protoc編譯.protoc文件;
- 在你的工程中import pb_encode.c, pb_decode.c 和 pb_common.c
demo具體參考nanopb中example/simple工程,編譯.proto文件的命令可參考以下:session
protomk: mkdir -p $(OUT_DIR) $(PROTOC) $(PROTOC_OPTS) --proto_path=$(PROTO_DIR) --nanopb_out=$(OUT_DIR) $(PROTO_DIR)/*.proto //OUT_DIR是%.proto文件編譯成功後,%.pb.c %.pb.h輸出的文件目錄 //PROTO_DIR是.proto文件所在的目錄位置 //PROTOC和PROTOC_OPTS的定義在../../extra/nanopb.mk
//extra/nanopb.mk ifneq "$(wildcard $(NANOPB_DIR)/generator-bin)" "" # Binary package PROTOC = $(NANOPB_DIR)/generator-bin/protoc PROTOC_OPTS = else # Source only or git checkout PROTOC = protoc ifdef WINDOWS PROTOC_OPTS = --plugin=protoc-gen-nanopb=$(NANOPB_DIR)/generator/protoc-gen-nanopb.bat else PROTOC_OPTS = --plugin=protoc-gen-nanopb=$(NANOPB_DIR)/generator/protoc-gen-nanopb endif endif
我本身的工程在ubuntu18.04上此命令打印出來以下:app
protoc --plugin=protoc-gen-nanopb=/media/pc-name/nanopb-nanopb-0.3.9.2/generator/protoc-gen-nanopb --proto_path=./proto --nanopb_out=./out ./proto/*.proto
遇到的問題
問題1:make失敗
Traceback (most recent call last): File "../../generator/nanopb_generator.py", line 2123, in <module> main_cli() File "../../generator/nanopb_generator.py", line 2019, in main_cli results = process_file(fdesc.name, fdesc, options, other_files) File "../../generator/nanopb_generator.py", line 1954, in process_file headerdata = ''.join(f.generate_header(includes, headerbasename, options)) File "../../generator/nanopb_generator.py", line 1610, in generate_header yield msg.fields_declaration(self.dependencies) + '\n' File "../../generator/nanopb_generator.py", line 1169, in fields_declaration defval = self.default_value(dependencies) File "../../generator/nanopb_generator.py", line 1299, in default_value desc = google.protobuf.descriptor.MakeDescriptor(optional_only) File "/home/pc-name/.local/lib/python3.6/site-packages/google/protobuf/descriptor.py", line 1077, in MakeDescriptor _message.default_pool.Add(file_descriptor_proto) TypeError: Couldn't build proto file into descriptor pool! Invalid proto descriptor for file "a8332bcbde22f967a60b51afdddf1cd5.proto": NanoPBOptions.long_names: "NanoPBOptions.long_names" is already defined in file "nanopb.proto". NanoPBOptions.packed_struct: "NanoPBOptions.packed_struct" is already defined in file "nanopb.proto". NanoPBOptions.packed_enum: "NanoPBOptions.packed_enum" is already defined in file "nanopb.proto". NanoPBOptions.skip_message: "NanoPBOptions.skip_message" is already defined in file "nanopb.proto". NanoPBOptions.no_unions: "NanoPBOptions.no_unions" is already defined in file "nanopb.proto". NanoPBOptions.anonymous_oneof: "NanoPBOptions.anonymous_oneof" is already defined in file "nanopb.proto". NanoPBOptions.proto3: "NanoPBOptions.proto3" is already defined in file "nanopb.proto". NanoPBOptions.enum_to_string: "NanoPBOptions.enum_to_string" is already defined in file "nanopb.proto". NanoPBOptions.fixed_length: "NanoPBOptions.fixed_length" is already defined in file "nanopb.proto". NanoPBOptions.fixed_count: "NanoPBOptions.fixed_count" is already defined in file "nanopb.proto". NanoPBOptions: "NanoPBOptions" is already defined in file "nanopb.proto".
解決方案:python2.7
pip uninstall protobuf pip install --no-binary=protobuf protobuf
問題2:grpcio-tools下載超時中斷
xiaoyanxia@xiaoyanxia-pc:/usr/bin$ pip3 install grpcio-tools Collecting grpcio-tools Using cached https://files.pythonhosted.org/packages/7a/b3/532a19e668920d3e1c1c832b4365734ffe6f510c9dd5e1c81240d82535ea/grpcio-tools-1.31.0.tar.gz Collecting protobuf<4.0dev,>=3.5.0.post1 (from grpcio-tools) Using cached https://files.pythonhosted.org/packages/30/79/510974552cebff2ba04038544799450defe75e96ea5f1675dbf72cc8744f/protobuf-3.13.0-cp36-cp36m-manylinux1_x86_64.whl Collecting grpcio>=1.31.0 (from grpcio-tools) Downloading https://files.pythonhosted.org/packages/e3/0e/f56aa1f8200ae3c5d38305e69f5920caa480c7ff54ae4d8a5f57d1d69fa4/grpcio-1.31.0.tar.gz (20.0MB) 1% |▌ | 327kB 14kB/s eta 0:22:34^C Operation cancelled by user xiaoyanxia@xiaoyanxia-pc:/usr/bin$ pip3 install grpcio Collecting grpcio Downloading https://files.pythonhosted.org/packages/e3/0e/f56aa1f8200ae3c5d38305e69f5920caa480c7ff54ae4d8a5f57d1d69fa4/grpcio-1.31.0.tar.gz (20.0MB) 4% |█▌ | 931kB 9.1kB/s eta 0:35:04Exception: Traceback (most recent call last): File "/usr/share/python-wheels/urllib3-1.22-py2.py3-none-any.whl/urllib3/response.py", line 302, in _error_catcher yield File "/usr/share/python-wheels/urllib3-1.22-py2.py3-none-any.whl/urllib3/response.py", line 384, in read data = self._fp.read(amt) File "/usr/share/python-wheels/CacheControl-0.11.7-py2.py3-none-any.whl/cachecontrol/filewrapper.py", line 60, in read data = self.__fp.read(amt) File "/usr/lib/python3.6/http/client.py", line 459, in read n = self.readinto(b) File "/usr/lib/python3.6/http/client.py", line 503, in readinto n = self.fp.readinto(b) File "/usr/lib/python3.6/socket.py", line 586, in readinto return self._sock.recv_into(b) File "/usr/lib/python3.6/ssl.py", line 1012, in recv_into return self.read(nbytes, buffer) File "/usr/lib/python3.6/ssl.py", line 874, in read return self._sslobj.read(len, buffer) File "/usr/lib/python3.6/ssl.py", line 631, in read v = self._sslobj.read(len, buffer) socket.timeout: The read operation timed out During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/pip/basecommand.py", line 215, in main status = self.run(options, args) File "/usr/lib/python3/dist-packages/pip/commands/install.py", line 353, in run wb.build(autobuilding=True) File "/usr/lib/python3/dist-packages/pip/wheel.py", line 749, in build self.requirement_set.prepare_files(self.finder) File "/usr/lib/python3/dist-packages/pip/req/req_set.py", line 380, in prepare_files ignore_dependencies=self.ignore_dependencies)) File "/usr/lib/python3/dist-packages/pip/req/req_set.py", line 620, in _prepare_file session=self.session, hashes=hashes) File "/usr/lib/python3/dist-packages/pip/download.py", line 821, in unpack_url hashes=hashes File "/usr/lib/python3/dist-packages/pip/download.py", line 659, in unpack_http_url hashes) File "/usr/lib/python3/dist-packages/pip/download.py", line 882, in _download_http_url _download_url(resp, link, content_file, hashes) File "/usr/lib/python3/dist-packages/pip/download.py", line 603, in _download_url hashes.check_against_chunks(downloaded_chunks) File "/usr/lib/python3/dist-packages/pip/utils/hashes.py", line 46, in check_against_chunks for chunk in chunks: File "/usr/lib/python3/dist-packages/pip/download.py", line 571, in written_chunks for chunk in chunks: File "/usr/lib/python3/dist-packages/pip/utils/ui.py", line 139, in iter for x in it: File "/usr/lib/python3/dist-packages/pip/download.py", line 560, in resp_read decode_content=False): File "/usr/share/python-wheels/urllib3-1.22-py2.py3-none-any.whl/urllib3/response.py", line 436, in stream data = self.read(amt=amt, decode_content=decode_content) File "/usr/share/python-wheels/urllib3-1.22-py2.py3-none-any.whl/urllib3/response.py", line 401, in read raise IncompleteRead(self._fp_bytes_read, self.length_remaining) File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__ self.gen.throw(type, value, traceback) File "/usr/share/python-wheels/urllib3-1.22-py2.py3-none-any.whl/urllib3/response.py", line 307, in _error_catcher raise ReadTimeoutError(self._pool, None, 'Read timed out.') urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.
解決方案:從新打開一個新的終端從新下載,就是這麼莫名奇妙,好幾回都是如此解決curl
問題3: make失敗
Traceback (most recent call last): File "../../generator/nanopb_generator.py", line 50, in <module> from .proto import nanopb_pb2 ModuleNotFoundError: No module named '__main__.proto'; '__main__' is not a package During handling of the above exception, another exception occurred: Traceback (most recent call last): File "../../generator/nanopb_generator.py", line 71, in <module> import proto.nanopb_pb2 as nanopb_pb2 ModuleNotFoundError: No module named 'proto.nanopb_pb2'
請進入generator/proto目錄下,執行***make all***命令
#nanopb-nanopb-0.3.9.2/generator/proto/Makefile all: nanopb_pb2.py plugin_pb2.py %_pb2.py: %.proto protoc --python_out=. $<
寫在最後:
很明顯能夠發現編譯.proto須要make 工具,請記得在編譯前要保證必要的工具安裝protocolbuffers
sudo apt-get install autoconf automake libtool curl make g++ unzip
參考來源 [1]: https://developers.google.com/protocol-buffers [2]: https://github.com/protocolbuffers/protobuf [3]: https://github.com/nanopb/nanopb