Python基礎_ 序列化

Python之路 - 序列化

先說個例子 , 當我們將一個字典或者列表再或者變量存入磁盤中 , 而存入磁盤后原本數(shù)據(jù)類型就得不到保持了 . 這個時候我們就得用序列化和反序列化了

序列化是將對象進行存儲時保持當時對象的狀態(tài) , 實現(xiàn)其生命周期的延長

反序列化則是將存儲的對象讀取出來并轉成原本的數(shù)據(jù)類型

序列化的目的

  1. 以某種存儲形式使自定義對象持久化
  2. 將對象從一個地方傳遞到另一個地方
  3. 使程序更具維護性

此時應該想到 eval :那么問題來了 , 序列化所達到的功能我用eval()也能達到啊 , eval()直接就可以把字符串轉換成python解釋器能解釋的代碼 , 即可以直接將字符串中的字典 , 列表都轉成原來的數(shù)據(jù)類型 . 但是要注意的是 , eval本來就是將字符串內容轉換成python可以執(zhí)行的代碼 , 并執(zhí)行它 , 這樣看來eval就不安全了 , 因為如果在我能讀取的內容中含有一些其他的 ' 危險代碼 ' 如 ' 刪除文件 ' , 于是造成了毀滅性的打擊 , 所以eval是存在風險的

Python為我們提供了三個序列化工具 , 分別是 json , pickle , shelve

json :four_leaf_clover:

用于字符串和python數(shù)據(jù)類型之間進行轉換 , 因為json表示出來就是一個字符串

json模塊提供了四個方法

方法 描述
dump 接收一個文件句柄 , 將原數(shù)據(jù)類型轉換成字符串寫入文件
load 接收一個文件句柄 , 將文件中的字符串轉換成原數(shù)據(jù)類型返回
dumps 接收一個數(shù)據(jù)類型 , 將其轉換成字符串
loads 接收一個字符串 , 將其轉換成原數(shù)據(jù)類型

dump 和 load 實例

# 導入json模塊
import json
# 創(chuàng)建一個文件句柄
f = open('json_file','w')
# 創(chuàng)建一個字典
dic = {'k1':'v1','k2':'v2'}
# 將字典轉換成字符串寫入文件
json.dump(dic,f)
# 關閉文件
f.close()
# 創(chuàng)建一個文件句柄
f = open('json_file')
# 將文件中的字符串讀出并轉換成原數(shù)據(jù)類型
dic2 = json.load(f)
# 關閉文件句柄
f.close()
# 打印類型和結果
print(type(dic2),dic2)
# <class 'dict'> {'k1': 'v1', 'k2': 'v2'}

dumps 和 loads 實例

# 導入json模塊
import json
# 創(chuàng)建一個新列表
lst = ['1','2','3','4']
# 將列表轉換成字符串,用j_d來接收返回值
j_d = json.dumps(lst)
# 將字符串轉換成原數(shù)據(jù)類型,用j_s來接收返回值
j_s = json.loads(j_d)
# 打印j_d的值以及類型
print(j_d,type(j_d))
# ["1", "2", "3", "4"] <class 'str'>
# 打印j_s的值以及類型
print(j_s,type(j_s))
# ['1', '2', '3', '4'] <class 'list'>

loads的特殊情況

# 導入json模塊
import json
# 創(chuàng)建一個字符串,內部為一個字典
dic_s = "{'k1':'v1','k2':'v2','k3':3}"
# 將字符串轉換成字典
json.loads(dic_s)
# 解釋器出現(xiàn)報錯
# json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
'''
報錯原因,用json的loads功能時,字符串類型的字典中的字符串必須由 "" 表示
即上面的dic_s應該改為 '{"k1":"v1","k2":"v2","k3":3}'

結論:用json的loads功能時,字符串類型的字典中的字符串必須由 "" 表示
'''

PS : json可用于不同語言之間的數(shù)據(jù)交換

pickle :four_leaf_clover:

用于python特有的類型和python的數(shù)據(jù)類型間進行轉換

pickle模塊也提供了四個方法 , 與json一樣 dumps , dump , loads , load

由于pickle是對于python特有的類型 , 所以 load 和 loads方法不僅支持字典 , 列表 , 它還能把python中任意的數(shù)據(jù)類型進行序列化

-------dumps和loads--------
# 導入pickle模塊
import pickle
# 創(chuàng)建一個字典
dic = {'k1':'v1','k2':'v2'}
# 將字典轉換成二進制內容
p_d = pickle.dumps(dic)
# 將二進制內容轉換成字典
p_l = pickle.loads(p_d)
# 打印p_d
print(p_d)  
# b'\x80\x03}q\x00(X\x02\x00\x00\x00k2q\x01X\x02\x00\x00\x00v2q\x02X\x02\x00\x00\x00k1q\x03X\x02\x00\x00\x00v1q\x04u.'
# 打印p_d的類型
print(type(p_d))
# <class 'bytes'>
# 打印p_l
print(p_l)
# {'k2': 'v2', 'k1': 'v1'}
# 打印p_l的類型
print(type(p_l))
# <class 'dict'>
---------dump 和 load---------
# 創(chuàng)建一個文件句柄
f = open('pickle_file','wb')
# 寫入內容
pickle.dump('lyon',f)
# 關閉文件
f.close()
# 創(chuàng)建一個文件句柄
f = open('pickle_file','rb')
# 讀出內容
p_f = pickle.load(f)
# 關閉文件
f.close()
# 打印
print(p_f)
# lyon

但是pickle僅僅只能對python中的數(shù)據(jù)進行序列化 , 反序列化時其他語言就無法讀懂了這是什么了 , 所以我們一般用推薦使用json

shelve :four_leaf_clover:

shelve也是python提供給我們的序列化工具 , 比pickle用起來簡單一些

shelve只提供給我們一個open方法 , 是用key來訪問的 , 使用起來和字典類似

# 導入shelve模塊
import shelve
# shelve提供open方法
f = shelve.open('shelve_file')
# 直接對文件句柄進行操作,就可以寫入文件中
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  
# 關閉文件
f.close()
# 打開文件
f1 = shelve.open('shelve_file')
# 直接用key取值,key不存在就報錯
existing = f1['key']
# 關閉文件
f1.close()
# 打印結果
print(existing)
# {'float': 9.5, 'int': 10, 'string': 'Sample data'}

shelve不支持多個應用同時往一個數(shù)據(jù)庫進行操作 , 所以當我們知道我們的應用如果只進行操作 , 我們可以設置shelve.open() 方法的參數(shù)來進行

shelve.open(filename, flag='c', protocol=None, writeback=False)

import shelve
# flag參數(shù)為設置操作模式,r 設置只讀模式
f = shelve.open('shelve_file', flag='r')
existing = f['key']
f.close()
print(existing)

writeback參數(shù) , 可以減少我們出錯的概率 , 并且讓對象的持久化對用戶更加的透明了 ; 但這種方式并不是所有的情況下都需要 , 首先 , 使用writeback以后 , shelf在open()的時候會增加額外的內存消耗 , 并且當數(shù)據(jù)庫在close()的時候會將緩存中的每一個對象都寫入到數(shù)據(jù)庫 , 這也會帶來額外的等待時間 , 因為shelve沒有辦法知道緩存中哪些對象修改了 , 哪些對象沒有修改 , 因此所有的對象都會被寫入

import shelve
f1 = shelve.open('shelve_file')
print(f1['key'])
f1['key']['new_value'] = 'this was not here before'
f1.close()
# 設置writeback
f2 = shelve.open('shelve_file', writeback=True)
print(f2['key'])
f2['key']['new_value'] = 'this was not here before'
f2.close()
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末钦扭,一起剝皮案震驚了整個濱河市烟央,隨后出現(xiàn)的幾起案子呀酸,更是在濱河造成了極大的恐慌,老刑警劉巖咱娶,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件席函,死亡現(xiàn)場離奇詭異求摇,居然都是意外死亡峰鄙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門套蒂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钞支,“玉大人,你說我怎么就攤上這事操刀∷感” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵骨坑,是天一觀的道長信夫。 經常有香客問我,道長卡啰,這世上最難降的妖魔是什么静稻? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮匈辱,結果婚禮上振湾,老公的妹妹穿的比我還像新娘。我一直安慰自己亡脸,他們只是感情好押搪,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著浅碾,像睡著了一般大州。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上垂谢,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天厦画,我揣著相機與錄音,去河邊找鬼。 笑死根暑,一個胖子當著我的面吹牛力试,可吹牛的內容都是我干的。 我是一名探鬼主播排嫌,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼畸裳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了淳地?” 一聲冷哼從身側響起怖糊,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颇象,沒想到半個月后伍伤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡夯到,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了饮亏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耍贾。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖路幸,靈堂內的尸體忽然破棺而出荐开,到底是詐尸還是另有隱情,我是刑警寧澤简肴,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布晃听,位于F島的核電站,受9級特大地震影響砰识,放射性物質發(fā)生泄漏能扒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一辫狼、第九天 我趴在偏房一處隱蔽的房頂上張望初斑。 院中可真熱鬧,春花似錦膨处、人聲如沸见秤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鹃答。三九已至,卻和暖如春突硝,著一層夾襖步出監(jiān)牢的瞬間测摔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工解恰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留避咆,地道東北人舟肉。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像查库,于是被迫代替她去往敵國和親路媚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內容