1. 程式人生 > >json、pickle與shelve模組

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'])