六 json&pickle模組
之前我們學習過用eval內建方法可以將一個字串轉成python物件,不過,eval方法是有侷限性的,對於普通的資料型別,json.loads和eval都能用,但遇到特殊型別的時候,eval就不管用了,所以eval的重點還是通常用來執行一個字串表示式,並返回表示式的值。
1 import json 2 x="[null,true,false,1]" 3 print(eval(x)) #報錯,無法解析null型別,而json就可以 4 print(json.loads(x))
什麼是序列化?
我們把物件(變數)從記憶體中變成可儲存或傳輸的過程稱之為序列化,在Python中叫pickling,在其他語言中也被稱之為serialization,marshalling,flattening等等,都是一個意思。
為什麼要序列化?
1:持久儲存狀態
需知一個軟體/程式的執行就在處理一系列狀態的變化,在程式語言中,'狀態'會以各種各樣有結構的資料型別(也可簡單的理解為變數)的形式被儲存在記憶體中。
記憶體是無法永久儲存資料的,當程式運行了一段時間,我們斷電或者重啟程式,記憶體中關於這個程式的之前一段時間的資料(有結構)都被清空了。
在斷電或重啟程式之前將程式當前記憶體中所有的資料都儲存下來(儲存到檔案中),以便於下次程式執行能夠從檔案中載入之前的資料,然後繼續執行,這就是序列化。
具體的來說,你玩使命召喚闖到了第13關,你儲存遊戲狀態,關機走人,下次再玩,還能從上次的位置開始繼續闖關。或如,虛擬機器狀態的掛起等。
2:跨平臺資料互動
序列化之後,不僅可以把序列化後的內容寫入磁碟,還可以通過網路傳輸到別的機器上,如果收發的雙方約定好實用一種序列化的格式,那麼便打破了平臺/語言差異化帶來的限制,實現了跨平臺資料互動。
反過來,把變數內容從序列化的物件重新讀到記憶體裡稱之為反序列化,即unpickling。
如何序列化之json和pickle:
json
如果我們要在不同的程式語言之間傳遞物件,就必須把物件序列化為標準格式,比如XML,但更好的方法是序列化為JSON,因為JSON表示出來就是一個字串,可以被所有語言讀取,也可以方便地儲存到磁碟或者通過網路傳輸。JSON不僅是標準格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。
JSON表示的物件就是標準的JavaScript語言的物件,JSON和Python內建的資料型別對應如下:
1 import json 2 3 dic={'name':'alvin','age':23,'sex':'male'} 4 print(type(dic))#<class 'dict'> 5 6 j=json.dumps(dic) 7 print(type(j))#<class 'str'> 8 9 10 f=open('序列化物件','w') 11 f.write(j) #-------------------等價於json.dump(dic,f) 12 f.close() 13 #-----------------------------反序列化<br> 14 import json 15 f=open('序列化物件') 16 data=json.loads(f.read())# 等價於data=json.load(f)
import json
#dct="{'1':111}"#json 不認單引號
#dct=str({"1":111})#報錯,因為生成的資料還是單引號:{'one': 1}
dct='{"1":"111"}'
print(json.loads(dct))
#conclusion:
# 無論資料是怎樣建立的,只要滿足json格式,就可以json.loads出來,不一定非要dumps的資料才能loads
注意點
import json #dct="{'1':111}"#json 不認單引號 #dct=str({"1":111})#報錯,因為生成的資料還是單引號:{'one': 1} dct='{"1":"111"}' print(json.loads(dct)) #conclusion: # 無論資料是怎樣建立的,只要滿足json格式,就可以json.loads出來,不一定非要dumps的資料才能loads
pickle
1 import pickle 2 3 dic={'name':'alvin','age':23,'sex':'male'} 4 5 print(type(dic))#<class 'dict'> 6 7 j=pickle.dumps(dic) 8 print(type(j))#<class 'bytes'> 9 10 11 f=open('序列化物件_pickle','wb')#注意是w是寫入str,wb是寫入bytes,j是'bytes' 12 f.write(j) #-------------------等價於pickle.dump(dic,f) 13 14 f.close() 15 #-------------------------反序列化 16 import pickle 17 f=open('序列化物件_pickle','rb') 18 19 data=pickle.loads(f.read())# 等價於data=pickle.load(f) 20 21 22 print(data['age'])
Pickle的問題和所有其他程式語言特有的序列化問題一樣,就是它只能用於Python,並且可能不同版本的Python彼此都不相容,因此,只能用Pickle儲存那些不重要的資料,不能成功地反序列化也沒關係。