Python學習筆記:序列化(Serialize)和反序列化(Deserialize)



1、使用場景一:保存內存中的數據到文件中,然后在下次要使用的時候再反序列化恢復數據,這樣使臨時中斷的工作得已恢復。比如虛擬機的快照等。
2、使用場景二:可以將數據序列化以后在兩種不同的語言中傳輸,比如Python數據類型轉成json格式再傳給Java
3、注意:json包只支持字典格式,作用是在不同語言程序之間進行數據交換,而pickle包則支持所有的python數據高效率的數據序列化,但因為python數據類型不能在不同的語言間通用所以只能python內部使用。



例1:這是一個最簡單的序列化和反序列化的例子,使用eval()還原這個字典dict1
dict1 = {"name":"tangwei","age":"18","profession":"professional"} file1 = open("test.txt","w",encoding="utf-8") file1.write(str(dict1)) # 文件中只能存字節型或者字符型
file1.close() file1 = open("test.txt","r") lines = file1.readlines() file1.close() for line in lines: dict2 = eval(line)  # 這僅僅是讀取文本,但是要放在內存中執行,還需要用到eval(),讓python把字符串當成代碼來執行
print("姓名",dict2["name"])

例2:以上代碼並非通用方法,因為eval()只在python使用,如果要再多語言中傳送和轉化數據可以用到json
import json dict1 = {"name":"tangwei","age":"18","profession":"professional"} file1 = open("test.txt","w",encoding="utf-8") file1.write(json.dumps(dict1)) # 文件中只能存字節型或者字符型,用dumps序列化,與json.dump(dict1,file1)功能一樣
file1.close() file1 = open("test.txt","r") # json_obj = json.load(file1) # 可以用load更簡便,也可以用下面的for循環 # print("姓名", json_obj["name"]) # 將讀出的字符串轉換成json格式
for line in file1: json_obj = json.loads(line)  # 用loads反序列化
    print("姓名", json_obj["name"]) file1.close()

例3:那么能不能將一個函數也序列化呢?如果能將函數和類都序列化,那么我再次取出的時候就可以直接恢復到中斷時的狀體,豈不是美滋滋?
# 注意:python的json包不能將函數和類對象之類的序列化,只能序列化字符和字節型數據。

import json def test1(name): print("111",name) dict1 = {"name":"tangwei","age":"18","method":test1} file1 = open("test.txt","w",encoding="utf-8") file1.write(json.dumps(dict1)) # 用dumps序列化只能是字節型或者字符型,test1是函數的內存地址,不能序列化,所以這里會報錯!
file1.close()

例4:如果一定要將函數序列化,那么只能用pickle包。
import pickle def test1(name): print("111",name) dict1 = {"name":"tangwei","age":"18","method":test1} file1 = open("test.txt","wb")  # 這里要用wb,寫字節類型
file1.write(pickle.dumps(dict1)) file1.close() file1 = open("test.txt","rb") # 將讀出的字符串轉換成json格式
for line in file1: # 用loads反序列化
    json_obj = pickle.loads(line) print("姓名", json_obj["name"]) # 可以直接執行同名函數,注意,這里的test1已經不是原來的test1了,因為序列化以后test1就釋放了
    json_obj["method"]("tangwei") file1.close()

 

 例5:實例化一個類的對象,使用追加“ab”模式,將同類對象序列化到一個文件中,取出的時候用下“yield”生成器取出對象。

import pickle


class MyPickle(object):

    def __init__(self, file_name):
        self.file_name = file_name

    def dump(self, obj):
        """
        序列化對象
        :param obj:
        :return:
        """
        with open(self.file_name, 'ab') as f:
            pickle.dump(obj, f)
            print('dump data', obj.__dict__)

    def loaditer(self):
        """
        迭代反序列化對象
        :return:
        """
        f = open(self.file_name, 'rb')
        while True:
            try:
                obj = pickle.load(f)
                yield obj
            except EOFError:
                print('EOFError')
                f.close()
                print(f.closed)
                break


class Person:
    def __init__(self, n, a):
        self.name = n
        self.age = a

    def show(self):
        print(self.name + "_" + str(self.age))


aa = Person("aGood", 2)
bb = Person("bGood", 3)
cc = Person("cGood", 4)

p = MyPickle('c.txt')
p.dump(aa)
p.dump(bb)
p.dump(cc)

iter_obj = p.loaditer()
while True:
    try:
        print(next(iter_obj).__dict__)
    except StopIteration:
        print('stop')
        break

例6:一個簡單的將類實例化的例子,但是這里如果用“ab”追加模式,每次反序列化的時候只能取得第一個對象

class DataPickle:
    def __init__(self, file, obj):
        self.file = file
        self.obj = obj

    def dump(self):
        f = open(self.file, 'wb')
        pickle.dump(self.obj, f)

    def load(self):
        f = open(self.file, 'rb')
        return pickle.load(f).__dict__
class School:
    def __init__(self,name):
        self.name = name

input_val = input("請輸入學校地址:")
school = School(input_val)
dp = DataPickle("data.txt", school)
dp.dump()

 

推薦寫法1:一次性寫或者讀,不用for循環一行行操作用load或者dump,用with不用考慮關閉文件的問題
import json file_path="文件路徑" account_data = {“name”:"tangwei","age":18} # 寫文件
with open(file_path, 'w') as f: json.dump(account_data,f) # 讀文件
with open(file_path,'r') as f: account_data= json.load(f)

 

推薦寫法2:因為json和pickle只支持序列化后的文件中只有一個json數據結構,如果有多個單獨的字典或者多個列表要存入就需要歸結成一個后存入,而且每次更新文件數據也是刪除舊數據重新寫如,很不方便,這時候可以用shelve包,支持任意類型任意存儲更新。

import sys,shelve,time,json
d = shelve.open("shelve_test")

info = {"age":22,"job":"it"}
name = ["tangwei","chenyadan"]

# 存入數據
d["name"] = name
d["info"] = info
d["date"] = time.time()
d.close()

# 讀取數據
d = shelve.open("shelve_test")
print(d.get("name"))
print(d.get("info"))
print(d.get("date"))

# 更新數據
d.update({"name":"chenmeifan"})
d.update({"info":"你好"})
d.update({"date":time.ctime(time.time())})
d.close()

#讀取新數據
d = shelve.open("shelve_test")
print("新數據",d.get("name"))
print("新數據",d.get("info"))
print("新數據",d.get("date"))
d.close()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM