?
10年積累的成都網(wǎng)站建設、網(wǎng)站建設經(jīng)驗,可以快速應對客戶對網(wǎng)站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡服務。我雖然不認識你,你也不認識我。但先網(wǎng)站策劃后付款的網(wǎng)站建設流程,更有唐山免費網(wǎng)站建設讓你可以放心的選擇與我們合作。
序列化、反序列化:
為什么要序列化?
內(nèi)存中的字典、鏈表如何保存到一個文件中?
如果是自己定義的類的實例,如何保存到一個文件中?
如何從文件中讀取數(shù)據(jù),并讓它們在內(nèi)存中再次變成自己對應的類的實例?
?
要設計一套協(xié)議(協(xié)議有版本,不同版本有不同的實現(xiàn),規(guī)則不一樣),按照某種規(guī)則,把內(nèi)存中數(shù)據(jù)保存到文件中,文件是一個字節(jié)序列,所以必須把數(shù)據(jù)轉(zhuǎn)換成字節(jié)序列,輸出到文件,這就是序列化;反之,從文件的字節(jié)序列恢復到內(nèi)存,就是反序列化;
?
數(shù)據(jù)轉(zhuǎn)換成二進制的有序序列的過程,稱為序列化;
從文件(有序的二進制序列)轉(zhuǎn)換成某種對象(list、dict等)的過程,稱為反序列化;
?
serialization序列化,將內(nèi)存中對象存儲下來,把它變成一個個字節(jié)(二進制);
deserialization反序列化,將文件的一個個字節(jié)(二進制)恢復成內(nèi)存中的對象;
?
注:
持久化,存在磁盤中,掉電不丟失;
序列化保存到文件,就是持久化;
可以將數(shù)據(jù)序列化后持久化(持久化前一定要序列化),或者網(wǎng)絡傳輸(通常big-edian模式),也可以從文件中或網(wǎng)絡接收到的字節(jié)序列反序列化;
每一種高級語言都有自己的序列化;
異構(gòu)平臺,兩端,如c/c++<-->python,要約定協(xié)議規(guī)定等;
?
?
?
python提供了pickle庫:
pickle僅限網(wǎng)絡兩端都是python程序;
import pickle
pickle.dumps(obj,protocol,fix_imports),對象序列化,不落地,在內(nèi)存中操作;
pickle.dump(obj,protocol,fix_imports),對象序列化到文件對象,存入文件;
pickle.loads(data,fix_imports,encoding,errors),對象反序列化,從內(nèi)存加載;
pickle.load(file,fix_imports,encoding,errors),對象反序列化,從文件讀取數(shù)據(jù);
?
內(nèi)建類型list、dict等,兩邊定義一致;
類、類屬性、類方法,僅序列化類名,兩端若類定義不一致,在調(diào)用后會有問題
對象屬性相關(guān)的,會序列化;而類方法、類屬性不會序列化(僅序列化類名)
?
總結(jié):
反序列化時,類是棋子,二進制序列就是鐵水;
類似,中央發(fā)往各州縣的錢模;適合分布式;
?
rpc,遠程過程調(diào)用原型;在網(wǎng)絡編程中極為重要,底層要實現(xiàn)的就是序列化、反序列化;
dict、list為內(nèi)建的類;
通常需要自定義類,兩邊的自定義要一致;
自定義的序列化要作校驗;
?
應用:
本地序列化的情況,應用較少;
一般來說,大多數(shù)場景都應用在網(wǎng)絡中,將數(shù)據(jù)序列化后通過網(wǎng)絡傳輸?shù)竭h程節(jié)點,遠程服務器上的服務接收到數(shù)據(jù)將其反序列化,就可使用了;
但,要注意,遠程接收端,反序列化時,必須有對應的數(shù)據(jù)類型,否則會報錯,尤其是自定義類等,遠程必須要有;
兩端python環(huán)境要一致;是推到遠端,不是遠端來拉;
現(xiàn)在,大多數(shù)項目,都不是單機的,也不是單服務的,需要通過網(wǎng)絡將數(shù)據(jù)傳送到其節(jié)點上,這就需要大量的序列化和反序列化;
python程序間可用pickle解決序列化、反序列化;
如果是跨平臺,跨語言、跨協(xié)議,pickle就不太適合了,就需要公共的協(xié)議,如xml、json、protocol buffer(glogle)等;
不同的協(xié)議,效率不同,學習曲線不同,適用不同場景,要根據(jù)不同的情況分析選型;
?
例(內(nèi)建類型list、dict等,兩邊定義一致):
import pickle
?
lst = 'a b c'.split()
d = dict(zip('abc',range(3)))
?
with open('/home/python/magedu/projects/cmdb/bin','wb') as f:
??? pickle.dump(lst,f)
??? pickle.dump(d,f)
?
with open('/home/python/magedu/projects/cmdb/bin','rb') as f:
??? tmp = pickle.load(f)
??? print(type(tmp))
??? print(tmp)
??? tmp = pickle.load(f)
??? print(tmp)
注:
運行結(jié)果:
['a', 'b', 'c']
{'a': 0, 'b': 1, 'c': 2}
將bin文件放至win上;
?
例(類、類屬性、類方法,僅序列化類名,兩端若類定義不一致,在調(diào)用后會有問題):
import pickle
?
class AA:
??? def show(self):
??????? print('abc')
?
aa = AA()
?
with open('/home/python/magedu/projects/cmdb/bin2','wb') as f:
??? pickle.dump(aa,f)
?
with open('/home/python/magedu/projects/cmdb/bin2','rb') as f:
??? tmp = pickle.load(f)?? #重新實例化后,賦給tmp,和aa是不同的對象
??? tmp.show()
注:
運行結(jié)果:
abc
將bin2傳至win主機:
linux和win下,兩端若定義的AA不一樣,則有問題;
?
例(類、類屬性、類方法,僅序列化類名,兩端若類定義不一致,在調(diào)用后會有問題):
import pickle
?
class AA:
??? cccc = 'abc'?? #類屬性
??? def show(self):
??????? print('abcd')
?
with open('bin3','wb') as f:
??? pickle.dump(AA(),f)
?
with open('bin3','rb') as f:
??? t = pickle.load(f)
??? t.show()
??? print(t.cccc)
注:
運行結(jié)果:
abcd
abc
將bin3傳至win主機:
?
例(對象屬性相關(guān)的,會序列化;而類方法、類屬性不會序列化(僅序列化類名)):
import pickle
?
class AA:
??? def __init__(self):
??????? self.aa = 'cc'?? #對象屬性,每個對象是獨立的,每個對象可改變此處定義
?
with open('bin4','wb') as f:
??? pickle.dump(AA(),f)
?
with open('bin4','rb') as f:
??? t = pickle.load(f)
??? print(t.aa)
注:
運行結(jié)果:
cc
將bin4傳至win主機:
?
?