1. 程式人生 > >六 json&pickle模組

六 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儲存那些不重要的資料,不能成功地反序列化也沒關係。