天天看點

python檔案IO二--序列化和反序列化

記憶體中的字典、連結清單、清單如何儲存到檔案中?

自定義的類的執行個體,如何儲存到檔案中?

又怎麼讀取才能讓他們在記憶體中再次變成自己對應的類的執行個體?

這就是序列化和反序列化

一、了解(serialization):

序列化和反序列化: 設計一套協定,按協定規則讀取、儲存資料到檔案中;檔案是一個位元組序列,是以必須把資料轉換成位元組序列,輸出到檔案;協定也分版本。用同樣版本的協定,保證讀取沒有問題。

二、序列化和反序列化定義:

  1. 序列化就是把資料變成可存儲或可傳輸的過程的,隻有序列化後的資料才可以寫入到磁盤或者通過網絡傳輸到Spark叢集的其他節點上。
  2. 反序列化則相反,反序列就是把序列化的變量重新轉到記憶體裡。
  3. 由于子產品shelve的Shelf方法依賴于pickle子產品,是以使用子產品shelve的Shelf方法加載不可信來源的資料也是不安全的。

序列化:将記憶體中的對象存儲下來,變成一個個位元組–>二進制

反序列化:将檔案中的一個個位元組恢複成記憶體中的對象。

持久化:序列化儲存到檔案就是持久化

可以将資料序列化後持久化,或網絡傳輸;也可以将從檔案或網絡接收的位元組序列反序列化。

三、目的:

1、落地,2、傳輸

四、python序列化标準庫:pickle

dump: 轉儲

pickle僅限于python内部序列化的問題,跨語言或網絡傳輸就不行了

  • pickle.dump() # 對象序列化到檔案對象,就是将python資料類型、對象以python特定格式的二進制,并存入檔案
  • pickle.load() # 對象反序列化,從檔案讀取python特定格式的二進制資料格式,轉換為python資料類型
  • pickle.dumps() # 對象序列化, 将python資料類型、對象轉換為python特定格式的二進制
  • pickle.loads() # 對象反序列化 将python特定格式的二進制資料格式轉換為python資料類型

五、通過自定義對象的序列化 了解序列化、反序列化過程:

案例實作

#!/usr/bin/env python3
# coding=utf-8
"""
@author: feng.luo
@time: 2022/3/25
@File: serialization_deserialization.py
"""

import pickle


class AA:
    TEST = 'ABC'

    def __init__(self):
        self.name = 'AAAA'

    @staticmethod
    def show():
        print('abc')


def serialization_test():
    # dump: 轉儲
    a = {'name': 'qiang', 'age': 11}
    b = 'abc'
    c = ['a', 'b', ['c', 'd']]
    with open('test.log', 'wb') as f:
        pickle.dump(a, f)
        pickle.dump(b, f)
        pickle.dump(c, f)

    with open('test.log', 'rb') as f:
        s = []
        for _ in range(3):
            s.append(pickle.load(f))
        print(s)


def obj_serialization_test():
    """
    自定義對象序列化
    """
    a1 = AA()
    with open('test.bin', 'wb') as f:
        pickle.dump(a1, f)


def obj_deserialization_test():
    # test.bin傳到另一個節點,反序列化。直接測試運作看會怎麼樣;
    # 然後建立子產品serialization_deserialization,并重新對象AA,或不寫AA,測試運作
    with open('test.bin', 'rb') as f:
        res = pickle.load(f)
        res.show()
        print(res.TEST)


if __name__ == '__main__':
    # serialization_test()
    obj_serialization_test()
           

通過分析序列化檔案test.bin可見:

  • 1、對象序列化,會儲存對象所在的子產品辨別serialization_deserialization,以及對象本身的辨別AA。
  • 2、類方法show、類屬性TEST都沒有被序列化
  • 3、對象屬性self.name則被序列化:因為每一個對象屬性都是不同的
  • 4、被序列化的對象,通過網絡傳輸到其他節點,反序列化後對象執行個體能夠運作的前提是其他節點必須有同樣的子產品定義,以及子產品内有相同辨別符AA的類定義,否則執行将失敗,報找不到這個子產品或方法。 如果其他節點的類方法、類屬性被重寫了,則得到不預期的結果,相當于偷梁換柱了。

反序列化的過程:類是模子,二進制序列就是鐵水。

六、應用:

本地序列化應用較少。大多數常見都應用在網絡中。将資料序列化後通過網絡傳輸到遠端節點,遠端伺服器上的服務将接收到的資料反序列化後,就可以使用了。

但是:遠端接收端,反序列化時必須有對應的資料類型,否則就會報錯。尤其是自定義類,必須遠端得有。

rpc的基本原則:序列化 <—> 反序列化

遠端過程調用:序列化 <—> 反序列化

序列化 整數傳輸大小端問題:網絡傳輸一般都是大端模式

七、序列化與反序列化的公共協定:

跨平台、跨語言的公共的序列化、反序列化協定:XML(易懂,但是廢資料太多)、Json(網絡傳輸)、Protocol Buffer(分布式場景)等。

不同的協定,效率不同,适用不同場景。講究效率,接近二進制比較合适;慢資料交換系統(比如内網),可能XML或Json方案比較合适。但是都不應該用先落地再讀取的方案。

八、Json: JavaScript Object Notation,JS對象标記、是一種輕量級的資料交換格式

它基于ECMAscript的一個子集,采用完全獨立于程式設計語言的文本格式來存儲和表示資料。采用文本格式來存儲和表示資料

Json資料類型value:

  • string:字元串。由雙引号包圍起來的任意字元的組合,可以有轉移字元
  • number:數值。整數、浮點數,可正負
  • object:無序的鍵值對集合,key必須是雙引号包圍的字元串,value可以是任意合法的值
  • array:清單
  • false:
  • true:
  • null:None

AJAX:異步傳輸資料

python類型 json類型對比

True true

False false

None null

str string

int integer

float float

list array

dict object

常用方法:

dumps json編碼

dump json編碼并存入檔案

loads json解碼

load json解碼,從檔案讀取資料

一般json編碼的資料很少落地,資料都是通過網路傳輸,傳輸的時候要考慮壓縮它-key值映射,減少網絡傳輸流量浪費

本質上json就是個文本、字元串,幾乎語言程式設計都支援json。

九、三方插件MessagePack:一個基于二進制高效的對象序列化類庫,可用于跨語言通信

可以像json那樣,在多種語言之間交換結構對象用法和jso、pickle一樣。

pip install msgpack-python
    import msgpack
    msgpack.dumps
    msgpack.dump
    msgpack.loads
    msgpack.load
           

MessagePack簡單易用,高效壓縮,效率比json更高。 –二進制格式存儲和表示資料

json應該更加廣泛,簡單-文本格式來存儲和表示資料