json、pickle與shelve模組
任何語言,都有自己的資料型別,那麼不同的語言怎麼找到一個通用的標準?
比如,後端用Python寫的,前端是js,那麼後端如果傳一個dic字典給前端,前端肯定不認。
所以就有了序列化這個概念。
什麼是序列化?
我們把物件(變數)從記憶體中變成可儲存或傳輸的過程稱之為序列化,在Python中叫pickling。
序列化之後,就可以把序列化後的內容寫入磁碟,或者通過網路傳輸進行前後端互動。
反過來,把變數內容從序列化的物件重新讀到記憶體裡稱之為反序列化,即unpickling。
json、pickle模板都可以實現序列化和反序列化,而我們知道的eval則是反序列化。
json.dumps():將Python物件通通轉為字串
import json a = 11 #---->'11' s = 'hello' #---->"hello"------>'"hello"' l = [1,2] #---->"[1,2]" dic = {'name':'nick'} #---->{"name":"nick"}----->'{"name":"nick"}' print(json.dumps(a)) print(json.dumps(s)) print(json.dumps(l)) print(json.dumps(dic))
結果:
11 #這四個結果都是字串
"hello"
[1, 2]
{"name": "nick"}
json.dumps()實際乾的兩件事:
1.把這個資料中的所有的單引號變為雙引號(有單引號就改為雙引號,沒有就不動)
2.把這個資料變為字串(在最外面加一對單引號)
json.loads():將字串轉為Python物件(與eval相似)
所以,用json現實檔案儲存:
import json dic = {'name':'nick'} str_dic = json.dumps(dic) #轉為字串 f_write = open('123.txt','w') f_write.write(str_dic) f_read = open('123.txt','r') data = f_read.read() data = json.loads(data) #轉回字典 print(type(data)) print(data)
結果:
<class 'dict'>
{'name': 'nick'}
json
如果我們要在不同的程式語言之間傳遞物件,就必須把物件序列化為標準格式,比如XML,但更好的方法是序列化為JSON,因為JSON表示出來就是一個字串,可以被所有語言讀取,也可以方便地儲存到磁碟或者通過網路傳輸。JSON不僅是標準格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。
注意,只有符合json標準格式規範的字串,才能被解析。在字串中,json只認雙引號,如下
123.txt: {"name": "nick"} with open('123.txt','r') as f_read: res = f_read.read() res = json.loads(res) print(type(res)) print(res) 結果:<class 'dict'> {'name': 'nick'} 123.txt: {'name': "nick"} #單引號不符合json的標準格式 with open('123.txt','r') as f_read: res = f_read.read() res = json.loads(res) print(type(res)) print(res) 結果:報錯
pickle
pickle和json的用法幾乎一樣,只是json是將Python物件轉為字串去儲存或傳輸,而pickle是將Python物件轉為位元組去儲存或傳輸,所以pickle適用的資料型別更多,比如類、物件。但是這樣的需求場景很少,所以一般來說,我們還是用json。
用pickle現實檔案儲存:
import pickle dic = {'name':'nick'} byte_dic = pickle.dumps(dic) print(byte_dic) with open('aaa.txt','wb') as f_write: #由於是byte,所以這裡要+b f_write.write(byte_dic) with open('aaa.txt','rb') as f_read: date = f_read.read() print(type(date)) date = pickle.loads(date) print(type(date)) print(date)
結果:
b'\x80\x03}q\x00X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00nickq\x02s.'
<class 'bytes'>
<class 'dict'>
{'name': 'nick'}
用eval內建方法可以將一個字串轉成python物件
用eval現實檔案儲存:
dic = {'name':'nick','age':20}
f_write = open('123.txt','w')
f_write.write(str(dic)) #寫入時直接f_write.write(dic)是報錯的,必須轉為str
f_read = open('123.txt','r')
data = f_read.read()
print(type(data)) #讀取是字串
data = eval(data) #eval轉為字典 print(type(data)) print(data)
結果:
<class 'str'>
<class 'dict'>
{'age': 20, 'name': 'nick'}
不過,eval方法是有侷限性的,對於普通的資料型別,json.loads和eval都能用,但遇到特殊型別的時候,eval就不管用了,所以就要用json。
用json.dumps()將字典轉為字串是序列化,用json.loads()將字串轉回字典是反序列化
用pickle.dumps()將字典轉為位元組是序列化,用pickle.loads()將位元組轉回字典是反序列化
用str()將字典轉為字串是序列化,用eval()將字串轉為字典也是反序列化
shelve
最後,簡單瞭解一下shelve模板,shelve和json、pickle屬於同一類,也是用於資料儲存和傳輸。
shelve是將pickle模板再進一步封裝,目的就是方便我們使用,可以直接把檔案當做一個字典來讀和寫,也就是直接操作鍵值對
shelve模組只有一個open函式,返回類似字典的物件,可讀可寫;key必須為字串,而值可以是python所支援的資料型別
import shelve #寫 f = shelve.open(r'abc.txt') #返回一個類似字典的檔案物件 f['name'] = 'nick' #插入鍵值對 f['info'] = {'age':20,'num':123321} #value是一個字典 f.close() f = shelve.open(r'abc.txt') #讀 print(f['info']['age']) #直接當做一個字典來讀,二級字典 print(f['name'])