一個人最重要的品質(zhì)镰踏,是懂得克制函筋,克制自己,不是沖動任性奠伪,克制自己的情緒跌帐。
而真正成熟的人,首先應(yīng)該是一個懂得克制自己欲望的人绊率!
總結(jié):
- pickle庫是一個很重要的庫谨敛,它的思想在后面很多庫中都有體現(xiàn)的;是一個必須要學(xué)的庫滤否!
- py2和py3 pickle協(xié)議可能是不同的脸狸;
- 游戲保存:內(nèi)存數(shù)據(jù)的保存(序列化與反序列化), 游戲公司對Python需求比較大顽聂;
- 所有語言編程都要考慮序列化與反序列化肥惭,使用pickle來認(rèn)識一下盯仪,json只是在某些方向紊搪,不是所有地方都用,json效率低下;
- 在序列化與反序列化中全景,類的屬性方法是共有耀石,不展示,在協(xié)議傳輸時必須一致; 實例 self是千變?nèi)f化的、自己的滞伟,會展示出來揭鳞;
內(nèi)存中的字典、列表梆奈、集合以及各種對象野崇,如何保存在一個文件中?
如何從文件中讀取數(shù)據(jù)亩钟,并讓它們在內(nèi)存中再次恢復(fù)成自己對應(yīng)的類的實例乓梨?
要設(shè)計一套協(xié)議,按照某種規(guī)則清酥,把內(nèi)存中數(shù)據(jù)保存到文件中扶镀。文件是一個字節(jié)序列,所以必須把數(shù)據(jù)轉(zhuǎn)換成字節(jié)焰轻;
序列臭觉,輸出到文件。這就是序列化辱志。反之蝠筑,從文件的字節(jié)序列恢復(fù)到內(nèi)存,就是反序列化揩懒。
序列化
序列化:我們把變量從內(nèi)存中變成可存儲或傳輸?shù)倪^程稱之為序列化菱肖,在Python中叫pickling。序列化之后旭从,就可以把序列化后的內(nèi)容寫入磁盤稳强,或者通過網(wǎng)絡(luò)傳輸?shù)絼e的機(jī)器上。
反序列化:反過來和悦,把變量內(nèi)容從序列化的對象(字節(jié)序列)重新讀到內(nèi)存里稱之為反序列化退疫,即unpickling。
Python提供了pickle模塊來實現(xiàn)序列化鸽素。
相關(guān)模塊
本節(jié)要介紹的就是Python內(nèi)置的幾個用于進(jìn)行數(shù)據(jù)序列化的模塊:
模塊名稱 | 描述 | 提供的api |
---|---|---|
json | 用于實現(xiàn)Python數(shù)據(jù)類型與通用(json)字符串之間的轉(zhuǎn)換; 不是所有地方都用褒繁,json效率低下 | dumps() 、dump() 馍忽、loads() 棒坏、 load() |
pickle | 用于實現(xiàn)Python數(shù)據(jù)類型與Python特定二進(jìn)制格式之間的轉(zhuǎn)換;不是一種很高效的協(xié)議序列化傳輸方案 | dumps()遭笋、dump()坝冕、loads()、load()瓦呼、 |
shelve | 專門用于將Python數(shù)據(jù)類型的數(shù)據(jù)持久化到磁盤喂窟,shelve是一個類似dict的對象,操作十分便捷 | open() |
pickle模塊
pickle模塊實現(xiàn)了用于對Python對象結(jié)構(gòu)進(jìn)行 序列化 和 反序列化 的二進(jìn)制協(xié)議,與json模塊不同的是pickle模塊序列化和反序列化的過程分別叫做pickling 和 unpickling:
pickling:是將Python對象轉(zhuǎn)換為字節(jié)流的過程磨澡;
unpickling:是將字節(jié)流二進(jìn)制文件或字節(jié)對象轉(zhuǎn)換回Python對象的過程碗啄;
pickle模塊提供的相關(guān)函數(shù)
pickle模塊提供的幾個序列化/反序列化的函數(shù)與json模塊基本一致:
說明:上面這幾個方法參數(shù)中,*號后面的參數(shù)都是Python 3.x新增的稳摄,目的是為了兼容Python 2.x稚字,具體用法請參看官方文檔。
# 將指定的Python對象通過pickle序列化作為bytes對象返回厦酬,而不是將其寫入文件
dumps(obj, protocol=None, *, fix_imports=True)
# 將通過pickle序列化后得到的字節(jié)對象進(jìn)行反序列化尉共,轉(zhuǎn)換為Python對象并返回
loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")
# 將指定的Python對象通過pickle序列化后寫入打開的文件對象中,等價于`Pickler(file, protocol).dump(obj)`
dump(obj, file, protocol=None, *, fix_imports=True)
# 從打開的文件對象中讀取pickled對象表現(xiàn)形式并返回通過pickle反序列化后得到的Python對象
load(file, *, fix_imports=True, encoding="ASCII", errors="strict)
# 示例 dump 和 load 方法弃锐;
#內(nèi)建方法袄友;
i = int(99)
s = 'ABC'
l = {'a':0x111111,'b':'abcde','c':[123]}
import pickle
with open('./ser.txt','wb') as f:
pickle.dump(i,f) # 對象i ,文件f;
pickle.dump(s,f)
pickle.dump(l,f)
#---------------------------------------------------------------------------------------------------------
??Kc.??X? ABCq .??}q (X? aq?J??? X? bq?X? abcdeq?X? cq?]q?K{au.
with open('./ser.txt','rb') as f:
tmp = pickle.load(f)
print(type(tmp),tmp)
tmp = pickle.load(f)
print(type(tmp),tmp)
tmp = pickle.load(f)
print(type(tmp),tmp)
#---------------------------------------------------------------------------------------------------------
<class 'int'> 99
<class 'str'> ABC
<class 'dict'> {'a': 1118481, 'b': 'abcde', 'c': [123]}
1.類的屬性方法在序列化中不展示 ,在源代碼中霹菊;
class AA:
aaaa = 0x111111
def show(self):
print('abc')
x = AA()
print(x)
with open('./ser.txt','wb') as f:
pickle.dump(x,f) # 對象i ,文件f;
with open('./ser.txt','rb') as f:
a = pickle.load(f)
print(type(a),hex(a.aaaa))
a.show()
#------------------------------------------------------------
<__main__.AA object at 0x000002704F7E8E48>
<class '__main__.AA'> 0x111111
abc
2. 序列化與反序列化 兩邊定義的類.方法要一致剧蚣;
#序列化寫入
class AA:
aaaa = 0x111111
def show(self):
print('abc')
x = AA()
ser = pickle.dumps(x)
print(ser)
with open('./ser.txt','wb') as f:
f.write(ser)
with open('./ser.txt','rb') as f:
a = pickle.load(f)
print(type(a),hex(a.aaaa))
a.show()
#--------------------------------------------------
b'\x80\x03c__main__\nAA\nq\x00)\x81q\x01.'
<class '__main__.AA'> 0x111111
abc
# 反序列化解讀
class AA:
aaaa = 60000
def show(self):
print('xyz123')
with open('./ser.txt','rb') as f:
a1 = pickle.load(f)
print((a1.aaaa))
a1.show()
#--------------------------------------------------
60000
xyz123
3. 類都是公有的,不展示旋廷;每一個self都是一個實例(千變?nèi)f化)鸠按;都是自己的特征,會被序列化饶碘;
class AA:
bbbb = 222 # 類都是公有的目尖,不展示
def __init__(self):
self.aaaa = 0x111111 # 每一個self都是一個實例;都是自己的特征扎运;
x = AA()
ser = pickle.dumps(x)
print(ser)
with open('./ser.txt','wb') as f:
f.write(ser)
#----------------------------------------------------------------------------------------------
b'\x80\x03c__main__\nAA\nq\x00)\x81q\x01}q\x02X\x04\x00\x00\x00aaaaq\x03J\x11\x11\x11\x00sb.'
序列化應(yīng)用——效率問題
一般來說瑟曲,本地序列化的情況,應(yīng)用較少豪治。大多數(shù)場景都應(yīng)用在網(wǎng)絡(luò)傳輸中洞拨。
將數(shù)據(jù)序列化后通過網(wǎng)絡(luò)傳輸?shù)竭h(yuǎn)程節(jié)點,遠(yuǎn)程服務(wù)器上的服務(wù)將接收到的數(shù)據(jù)反序列化后负拟,就可以使用了烦衣。
但是,要注意一點掩浙,遠(yuǎn)程接收端花吟,反序列化時必須有對應(yīng)的數(shù)據(jù)類型,否則就會報錯厨姚。尤其是自定義類衅澈,必須遠(yuǎn)程得有一致的定義。
現(xiàn)在遣蚀,大多數(shù)項目矾麻,都不是單機(jī)的,也不是單服務(wù)的芭梯。需要通過網(wǎng)絡(luò)將數(shù)據(jù)傳送到其他節(jié)點上去险耀,這就需要大量的序列化、反序列化過程玖喘。
但是甩牺,問題是,Python程序之間還可以都是用pickle解決序列化累奈、反序列化贬派,如果是跨平臺、跨語言澎媒、跨協(xié)議pickle就不太適合了搞乏,就需要公共的協(xié)議。例如XML戒努、Json请敦、Protocol Bu?er等,協(xié)議非常多储玫。
不同的協(xié)議侍筛,效率不同、學(xué)習(xí)曲線不同撒穷,適用不同場景匣椰,要根據(jù)不同的情況分析選型。