Python學習筆記__9.4章 序列化
1、概覽
在程序運行的過程中,所有的變量都是在內存中。但是一旦程序結束,變量所占用的內存就被操作系統全部回收。而如果要保存變量的修改,我們就可以用序列化。
我們把變量從內存中變成可存儲或傳輸的過程稱之為序列化,在Python中叫pickling。
序列化之後,就可以把序列化後的內容寫入磁盤,或者通過網絡傳輸到別的機器上
反過來,把變量內容從序列化的對象重新讀到內存裏稱之為反序列化,即unpickling。
2、pickle模塊
Python提供了pickle模塊來實現序列化 和 反序列化
1、序列化
d = dict(name='Bob', age=20, score=88)
# pickle.dumps()——將對象序列化為bytes,並打印出來,需要手動寫入文件
>>> import pickle # 導入pickle模塊
>>> pickle.dumps(d) # 將對象序列化成一個bytes
b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'
# pickle.dump()——將序列化的信息直接寫入file-like Object,不打印
>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f) # 將d序列化,二進制格式寫入f
>>> f.close() # 關閉文件對象
2、反序列化
# pickle.loads()——根據生成的bytes 反序列化
x=b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.' #將序列化出的bytes 賦值給 x
>>> pickle.loads(x) # 反序列化
{'age': 20, 'score': 88, 'name': 'Bob'}
# pickle.load()——讀取file-like Object 的數據 反序列化
>>> f = open('dump.txt', 'rb') #創建可讀文件對象。格式為二進制
>>> d = pickle.load(f) # 從f 中讀取數據,反序列化
>>> f.close()
>>> d
{'age': 20, 'score': 88, 'name': 'Bob'}
3、註意
反序列化出的變量和原來的變量是完全不相幹的對象,它們只是內容相同而已。
Pickle只能用於Python,並且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的數據
3、JSON的序列化
如果要在不同的編程語言之間傳遞對象,就必須把對象序列化為標準格式。而JSON表示出來就是一個字符串,可以被所有語言讀取,也可以方便地存儲到磁盤或者通過網絡傳輸。
Python對象到JSON格式的轉換需要json模塊,它調用的方法同pickle模塊類似。
d = dict(name='Bob', age=20, score=88)
1、序列化
# json.dumps()——序列化並打印
>>> import json
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'
# json.dump——直接把JSON寫入一個file-like Object
2、反序列化
# json.loads()——把JSON的字符串反序列化
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}
# json.load()——從file-like Object中讀取字符串並反序列化
3、class序列化為JSON
1、序列化
import json
class Student(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
s = Student('Bob', 20, 88)
print(json.dumps(s))
如果我們直接將Student的實例序列化為JSON,則會報錯。這是因為默認情況下,dumps()方法不知道如何將Student的實例變為一個JSON的{}對象。
而可選參數default可以把任意一個對象變成一個 可序列為 JSON的對象,我們只需要為Student專門寫一個轉換函數,再把函數傳進去即可。
def student2dict(std):
return {
'name': std.name,
'age': std.age,
'score': std.score
}
Student實例首先被student2dict()函數轉換成一個可序列為JSON的dict對象,然後再被順利序列化為JSON
>>> print(json.dumps(s, default=student2dict))
{"age": 20, "name": "Bob", "score": 88}
編寫專門的函數序列化,太過麻煩。更簡潔的方法如下:
# 把任意class的實例變為dict
# 將實例s,傳給 obj 參數,然後返回 obj.__dict__就是個dict
print(json.dumps(s, default=lambda obj: obj.__dict__))
通常class的實例都有一個__dict__屬性,它就是一個dict,用來存儲實例變量
>>> s.__dict__
{'name': 'Bob', 'age': 20, 'score': 88}
>>> type(s.__dict__)
<class 'dict'>
2、反序列化
loads()方法首先轉換出一個dict對象,然後,我們傳入的object_hook函數負責把dict轉換為Student實例
# dict 轉換為Student() 的函數
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}' # 需要反序列化的json字符串
>>> print(json.loads(json_str, object_hook=dict2student)) 將json_str通過dict2student 轉化為Student()
<__main__.Student object at 0x10cd3c190>
Python學習筆記__9.4章 序列化