日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python对Protobuf进行序列化与反序列化

發(fā)布時間:2023/12/9 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python对Protobuf进行序列化与反序列化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Python Protobuf

  • 1.了解Protobuf:
    • 1.1 Protobuf語法介紹:
  • 2. Python使用Protobuf:(windows平臺上)

1.了解Protobuf:

我們在使用protobuf之前首先要了解protobuf,那么什么是protobuf呢?

官方的解釋是:

protocol buffers 是一種與語言無關、平臺無關、可擴展的序列化結構數(shù)據(jù)的方法,它可用于(數(shù)據(jù))通信協(xié)議、數(shù)據(jù)存儲等。

Protocol Buffers 是一種靈活,高效,自動化機制的結構數(shù)據(jù)序列化方法-可類比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更為簡單。

你可以定義數(shù)據(jù)的結構,然后使用特殊生成的源代碼輕松的在各種數(shù)據(jù)流中使用各種語言進行編寫和讀取結構數(shù)據(jù)。你甚至可以更新數(shù)據(jù)結構,而不破壞由舊數(shù)據(jù)結構編譯的已部署程序。

簡單的來說,ProtoBuf和json、xml一樣是一種結構化的數(shù)據(jù)格式,用于數(shù)據(jù)通信的傳輸及數(shù)據(jù)的存儲。但ProtoBuf相比json和xml來說具有以下的優(yōu)點:

  • 性能好,效率高:是一種二進制的數(shù)據(jù)格式,比xml小3-5倍,其速度是xml的20-100倍。
  • 代碼生成機制,數(shù)據(jù)解析類自動生成:提供了根據(jù)proto文件生成對應的源文件代碼生成機制。windows(proto.exe)、linux平臺動態(tài)編譯生成
  • 支持向后和向前兼容:兼容以前和以后的其他版本,更新數(shù)據(jù)結構,不影響破壞原有的舊程序。
  • 支持多種編譯語言:提供了C++、python、java多種語言的支持。

缺點:

  • 其內部格式是二進制,導致數(shù)據(jù)可讀性差。

1.1 Protobuf語法介紹:

在Protobuf中,.proto文件相當于確定數(shù)據(jù)協(xié)議,數(shù)據(jù)結構中存在哪些數(shù)據(jù),數(shù)據(jù)類型是怎么樣的。先來看一個簡單的.proto文件的數(shù)據(jù)結構,然后再來詳細了解一下protobuf語法

syntax = "proto3";message SearchRequest {string query = 1;int32 page_number = 2;int32 result_per_page = 3; }
  • 該文件的第一行指定您正在使用proto3語法:如果您不這樣做,protobuf 編譯器將假定您正在使用proto2。這必須是文件的第一個非空的非注釋行。
  • 所述SearchRequest消息定義了三個字段(名稱/值對),每個字段都有一個名稱和類型,及唯一的數(shù)字標識符。

protobuf2中.proto文件中的數(shù)據(jù)結構由以下幾部分組成:

  • 關鍵字message:代表實體結構,由多個消息字段(field)組成。
  • 消息字段: 由數(shù)據(jù)類型、字段名、字段規(guī)則、字段唯一標識、默認值組成。
  • 數(shù)據(jù)類型:
    • 復合型數(shù)據(jù)類型:枚舉、message類型
    • 標準數(shù)據(jù)類型:整型、浮點、字符串等
  • 字段規(guī)則
    • required:必須初始化字段,如果沒有賦值,在數(shù)據(jù)序列化時會拋出異常
    • optional:可選字段,可以不賦值。如果沒有賦值,會使用默認值
    • repeated:表示該字段可以重復任意次數(shù),包括0次。重復數(shù)據(jù)的順序將會保存在protocol buffer中。
  • 字段唯一標識:每個字段都有唯一的數(shù)字標識符。用于標記該字段在序列化后的二進制數(shù)據(jù)中輸在的field,每個字段的唯一數(shù)字標識符在message內部都是獨一無二的。
  • 默認值:在定義消息字段時可以給出默認值

Potobuf3與Protobuf2不同的地方:

1、字段規(guī)則:

  • 字段前取消了required和optional兩個關鍵字,目前只保留了repeated關鍵字。
  • 修飾消息的字段修飾符必須是singular、或repeated。
    • singular:一個格式良好的消息應該有0個或者1個這種字段(但是不能超過1個)。
    • repeated:在一個格式良好的消息中,這種字段可以重復任意多次(包括0次)。重復的值的順序會被保留。

2、取消了設置默認值:

  • string默認為字符串
  • bytes默認為空bytes
  • bool默認為false
  • 數(shù)字類型默認為0
  • 枚舉類型默認為第一個枚舉定義的第一個值。且第一個值必須為0。

3、支持的數(shù)據(jù)類型有:

double、float、int32、int64、uint32、uint64、sint32、sint64、fixed32、fixed64、sfixed32、sfixed64、bool、string、bytes

4、分配標識符:

正如上述文件格式,在消息定義中,每個字段都有唯一的一個數(shù)字標識符。這些標識符是用來在消息的二進制格式中識別各個字段的,一旦開始使用就不能夠再改變。

注意:[1,15]之內的標識號在編碼的時候會占用一個字節(jié)。[16,2047]之內的標識號則占用2個字節(jié)。所以應該為那些頻繁出現(xiàn)的消息元素保留 [1,15]之內的標識號。切記:要為將來有可能添加的、頻繁出現(xiàn)的標識號預留一些標識號。

最小的標識號可以從1開始,最大到2^29 - 1, or 536,870,911。不可以使用其中的[19000-19999]的標識號, Protobuf協(xié)議實現(xiàn)中對這些進行了預留。如果非要在.proto文件中使用這些預留標識號,編譯時就會報錯。


2. Python使用Protobuf:(windows平臺上)

1. 首先下載平臺對應的proto編譯器,根據(jù)平臺下載對應版本:

https://github.com/google/protobuf/releases

windows平臺可以下win64。

然后將壓縮包解壓,將壓縮包中bin目錄下的proto.exe文件放到項目目錄下,用于將來編譯.proto文件。

在該目錄下執(zhí)行:protoc.exe --version判斷是否可用

然后執(zhí)行:pip install protobuf 安裝protobuf模塊

2. 在項目目錄下創(chuàng)建test.proto文件,定義數(shù)據(jù)結構

syntax = "proto3"; // 指定protobuf語法版本 package Protobuf_test; // 包名message AddressBook {repeated Person people = 1; }message Person {string name = 1;int32 id = 2;string email = 3;float money = 4;bool work_status = 5;repeated PhoneNumber phones = 6;MyMessage maps = 7;}message PhoneNumber {string number = 1;PhoneType type = 2; }enum PhoneType {MOBILE = 0;HOME = 1;WORK = 2; }message MyMessage {map<int32, int32> mapfield = 1; }

3. 使用proto.exe編譯.proto文件,生成一個對應的.py的文件

在項目目錄下執(zhí)行:proto.exe --python_out = ./ test.proto

4. 接下來就可以編寫python程序進行序列化和反序列化了

import test_pb2address_book = test_pb2.AddressBook() person = address_book.people.add()person.id = 1 person.name = 'lichungang' person.email = 'xxxxx@163.com' person.money = 1 person.work_status = Truephone_number = person.phones.add() phone_number.number = "123456" phone_number.type = test_pb2.MOBILEmaps = person.maps # maps類型是singular,不是repeated類型無法使用add() maps.mapfield[1] = 1 maps.mapfield[2] = 2# 序列化 serialize_to_string = address_book.SerializeToString() print(serialize_to_string, type(serialize_to_string))# 反序列化 address_book.ParseFromString(serialize_to_string)for person in address_book.people:print("p_id:{},p_name:{},p_email:{},p_money:{},p_workstatu:{}".format(person.id, person.name, person.email, person.money, person.work_status))for phone_number in person.phones:print(phone_number.number, phone_number.type)for key in person.maps.mapfield:print(key, person.maps.mapfield[key])

結果:

b'\n<\n\nlichungang\x10\x01\x1a\rxxxxx@163.com%\x00\x00\x80?(\x012\x08\n\x06123456:\x0c\n\x04\x08\x01\x10\x01\n\x04\x08\x02\x10\x02' <class 'bytes'> p_id:1,p_name:lichungang,p_email:xxxxx@163.com,p_money:1.0,p_workstatu:True 123456 0 1 1 2 2

參考:
https://www.cnblogs.com/sanshengshui/p/9739521.html

https://blog.csdn.net/caisini_vc/article/details/5599468

總結

以上是生活随笔為你收集整理的Python对Protobuf进行序列化与反序列化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。