一、說明
早上看到Python使用pickle進行序列化和反序列化,然后發現面臨的一個獲取不到返回值的框架,似乎可以通過在框架中先序列化,然后在外部進行反序列化的方法來實現。就研究了一下pickle庫的具體使用。
本身也沒什么復雜,一方面還是怕忘記,另一方面是自從學Java聽到反序化這個詞開始就有一種莫明其妙的恐具感總覺得是什么高大上的東西。Java反序列化可參見“Java反序列化漏洞實現”。
二、本地的序列化與反序列化實現
import pickle class BeSerializing: def __init__(self): self.var = "a test string." def print_var(self): print(f"self var value is:{self.var}") class Serializing: def do_serializing(self): obj = BeSerializing() # with的好處是會最后自動釋放獲取的資源,對於文件就是最后會自己close() with open("test_pickle.obj", "wb") as file_handler: # 序列化,將對象寫到文件 pickle.dump(obj, file_handler) class DeSerializing: def do_serializing(self): with open("test_pickle.obj", "rb") as file_handler: # 反序列化,將對象從文件中還原 # 注意,雖然python的變量不需要使用前先定義類型,但使用時是要被格式化成確定類型的 # 所以,如果反序列化類和被序列化類不在同一文件中,那么需要將被序列化類import進來,不然會因找不到被反序列化類而反序列化失敗 obj = pickle.load(file_handler) print(f"obj type: {type(obj)}\n" f"obj.var value: {obj.var}") if __name__ == "__main__": obj_se = Serializing() obj_se.do_serializing() obj_de = DeSerializing() obj_de.do_serializing()
運行結果如下,可以看到成功反序列化並打印出被序列化的對象的變量的值:
三、網絡的序列化與反序列化實現
上邊我們是以文件作為中介實現序列化與反序列化的,但如果到網絡中就沒有文件作為中介。此時可以使用pickle.dumps()和pickle.loads()進行序列化與反序列化。
import binascii import pickle class BeSerializing: def __init__(self): self.var = "a test string." def print_var(self): print(f"self var value is:{self.var}") class NoFileSerializing: def do_serializing(self): obj_src = BeSerializing() # 二進制直接decode可能很多位置沒法解碼(codec can't decode) obj_src_bytes = pickle.dumps(obj_src) # 所以先轉成ascii碼形式的16進制再decode obj_src_str = binascii.b2a_hex(obj_src_bytes).decode(encoding="ascii") # 模擬網絡遠端獲取傳過來的字符串 obj_dst_str = obj_src_str # 還原成二進制 obj_dst_bytes = binascii.a2b_hex(obj_dst_str.encode(encoding="ascii")) # 反序列化 obj_dst = pickle.loads(obj_dst_bytes) print(obj_dst.var) if __name__ == "__main__": obj_nf = NoFileSerializing() obj_nf.do_serializing()
執行結果如下:
參考: