模塊--序列化

 

1     序列化

1.1   什麼是序列化

將本來的字典、列表等內容轉換成一個字符串的過程就叫作序列化java

 

序列:列表、元祖、字符串、bytespython

序列化:字符串、bytesjson

1.2   爲何要轉成字符串?

可以在網絡上傳輸的只能是bytes,安全

可以存儲在文件裏的只有bytes和str網絡

序列化的目的數據結構

一、以某種存儲形式使自定義對象持久化函數

二、將對象從一個地方傳遞到另外一個地方。學習

三、使程序更具維護性。spa

 

 

1.3   爲何要有序列化模塊?

好比,咱們在python代碼中計算的一個數據須要給另一段程序使用,那咱們怎麼給?code

如今咱們能想到的方法就是存在文件裏,而後另外一個python程序再從文件裏讀出來。

可是咱們都知道,對於文件來講是沒有字典這個概念的,因此咱們只能將數據轉換成字典放到文件中。

你必定會問,將字典轉換成一個字符串很簡單,就是str(dic)就能夠辦到了,爲何咱們還要學習序列化模塊呢?

沒錯序列化的過程就是從dic 變成str(dic)的過程。如今你能夠經過str(dic),將一個名爲dic的字典轉換成一個字符串,

可是你要怎麼把一個字符串轉換成字典呢?

聰明的你確定想到了eval(),若是咱們將一個字符串類型的字典str_dic傳給eval,就會獲得一個返回的字典類型了。

eval()函數十分強大,可是eval是作什麼的?e官方demo解釋爲:將字符串str當成有效的表達式來求值並返回計算結果。

BUT!強大的函數有代價。安全性是其最大的缺點

想象一下,若是咱們從文件中讀出的不是一個數據結構,而是一句"刪除文件"相似的破壞性語句,那麼後果實在不堪設設想。

而使用eval就要擔這個風險。

因此,咱們並不推薦用eval方法來進行反序列化操做(將str轉換成python中的數據結構)

s="{1:2}"
d='[1,2,3]'
print(eval(s))      #{1: 2}
print(eval(d))      #[1, 2, 3]

 

# eval 要謹慎的使用,用戶的輸入/網絡上接收的數據/文件中的內容

# eval('import os;os.remove('c:')')

 

 

2     json模塊—通用但限制多

Json模塊提供了四個功能:dumps、dump、loads、load

# json

# dumps loads

    # 在內存中作數據轉換 :

        # dumps 數據類型 轉成 字符串 序列化  (在內存中操做)

        # loads 字符串 轉成 數據類型 反序列化

# dump load

    # 直接將數據類型寫入文件,直接從文件中讀出數據類型

        # dump 數據類型 寫入 文件 序列化

        # load 文件 讀出 數據類型 反序列化

# json是全部語言都通用的一種序列化格式

    # 只支持 列表 字典 字符串 數字

    # 字典的key必須是字符串

 

2.1   dumps和loads

dic = {'key' : 'value','key2' : 'value2'}
ret = json.dumps(dic)   #序列化
print(dic,type(dic))    #{'key': 'value', 'key2': 'value2'} <class 'dict'>
print(ret,type(ret))    #{"key": "value", "key2": "value2"} <class 'str'>

res = json.loads(ret)   #反序列化
print(res,type(res))    #{'key': 'value', 'key2': 'value2'} <class 'dict'>

2.1.1 問題一:

能夠看到序列化和反序列化後key值的類型-----》字符串類型,

因此對於字典的約束:key是字符串類型

dic = {1:'value',2:'value2'}
ret = json.dumps(dic)   #序列化
print(dic,type(dic))    #{1: 'value', 2: 'value2'} <class 'dict'>
print(ret,type(ret))    #{"1": "value", "2": "value2"} <class 'str'>
res = json.loads(ret)   #反序列化
print(res,type(res))    #{'1': 'value', '2': 'value2'} <class 'dict'>

 

 

2.1.2 問題二:

 

dic = {1 : [1,2,3],2 : (4,5,'aa')}
ret = json.dumps(dic)  # 序列化
print(dic,type(dic))    #{1: [1, 2, 3], 2: (4, 5, 'aa')} <class 'dict'>
print(ret,type(ret))    #{"1": [1, 2, 3], "2": [4, 5, "aa"]} <class 'str'>
res = json.loads(ret) # 反序列化
print(res,type(res))    #{'1': [1, 2, 3], '2': [4, 5, 'aa']} <class 'dict'>

 

 

2.1.3 問題三:

s = {1,2,'aaa'}
json.dumps(s)       #TypeError

2.1.4 問題四:

json.dumps({(1,2,3):123})   #TypeError: keys must be a string

2.1.5 問題五:不支持連續的存 取

dic = {'key1' : 'value1','key2' : 'value2'}
with open('json_file','a') as f:
    json.dump(dic,f)
    json.dump(dic,f)
    json.dump(dic,f)

with open('json_file','r') as f:
    dic = json.load(f)
print(dic.keys())

2.1.6 經常使用於文件操做傳輸

#向文件中記錄字典
dic = {'key' : 'value','key2' : 'value2'}
ret = json.dumps(dic)
with open('json_file','a') as f:
    f.write(ret)

#從文件中讀取字典
with open('json_file','r') as f:
    str_dic = f.read()
di = json.loads(str_dic)
print(di)

 

注意:

json只能識別一個字典,若是多個字典在一行,當反序列化的時候就會報錯,因此能夠把字典放不一樣的行,並在讀文件時,readline一行一行讀

 

# 需求 :就是想要把一個一個的字典放到文件中,再一個一個取出來???

dic = {'key1' : 'value1','key2' : 'value2'}

with open('json_file','a') as f:
    str_dic = json.dumps(dic)
    f.write(str_dic+'\n')
    str_dic = json.dumps(dic)
    f.write(str_dic + '\n')
    str_dic = json.dumps(dic)
    f.write(str_dic + '\n')

with open('json_file','r') as f:
    for line in f:
        dic = json.loads(line.strip())
        print(dic.keys())

 

2.2   結論:

# json 在全部的語言之間都通用 : json序列化的數據 在python上序列化了 那在java中也能夠反序列化

# 可以處理的數據類型是很是有限的 : 字符串 列表 字典 數字

# 字典中的key只能是字符串

 

2.3   dump和load

dic = {'key1' : 'value1','key2' : 'value2'}
with open('json_file','a') as f:
    json.dump(dic,f)

with open('json_file','r') as f:
    dic = json.load(f)
print(dic)

 

結論:Dump和load直接操做文件

 

2.4   其餘參數

data = {'username':['李華','二愣子'],'sex':'male','age':16}
json_dic2 = json.dumps(data,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False)
print(json_dic2)

結果:

{

    "age":16,

    "sex":"male",

    "username":[

        "李華",

        "二愣子"

    ]

}

Skipkeys:默認值是False,若是dict的keys內的數據不是python的基本類型(str,unicode,int,long,float,bool,None),設置爲False時,就會報TypeError的錯誤。此時設置成True,則會跳過這類key

ensure_ascii:,當它爲True的時候,全部非ASCII碼字符顯示爲\uXXXX序列,只需在dump時將ensure_ascii設置爲False便可,此時存入json的中文便可正常顯示。)

indent:應該是一個非負的整型,若是是0就是頂格分行顯示,若是爲空就是一行最緊湊顯示,不然會換行且按照indent的數值顯示前面的空白分行顯示,這樣打印出來的json數據也叫pretty-printed json

separators:分隔符,其實是(item_separator, dict_separator)的一個元組,默認的就是(‘,’,’:’);這表示dictionary內keys之間用「,」隔開,而KEY和value之間用「:」隔開。

 

sort_keys:將數據根據keys的值進行排序。

 


3     pickle模塊
 

用於序列化的兩個模塊

json,用於字符串 和 python數據類型間進行轉換

pickle,用於python特有的類型 和 python的數據類型間進行轉換

支持在python中幾乎全部的數據類型

 

pickle模塊提供了四個功能:dumps、dump(序列化,存)、loads(反序列化,讀)、load  (不只能夠序列化字典,列表...能夠把python中任意的數據類型序列化

 

3.1   特色:

(1)支持在python中幾乎全部的數據類型

(2)dumps 序列化的結果只能是字節

(3)只能在python中使用

(4)在和文件操做的時候,須要用rb wb的模式打開文件

(5)能夠屢次dump 和 屢次load

3.2   案例:

3.2.1 案例一:

import pickle
dic = {(1,2,3):{'a','b'},1:'abc'}
ret = pickle.dumps(dic)
print(ret)
#結果:b'\x80\x03}q\x00(K\x01K\........
#結論:dumps 序列化的結果只能是字節
print(pickle.loads(ret))    #{(1, 2, 3): {'b', 'a'}, 1: 'abc'}

3.2.2 案例二:

import pickle
dic = {(1,2,3):{'a','b'},1:'abc'}
with open('pickle_file','wb') as f:
    pickle.dump(dic,f)

with open('pickle_file','rb') as f:
    ret = pickle.load(f)
print(ret,type(ret))        #{(1, 2, 3): {'b', 'a'}, 1: 'abc'} <class 'dict'> 

3.2.3 案例三:能夠屢次dump 和 屢次load

dic = {(1,2,3):{'a','b'},1:'abc'}
dic1 = {(1,2,3):{'a','b'},2:'abc'}
dic2 = {(1,2,3):{'a','b'},3:'abc'}
dic3 = {(1,2,3):{'a','b'},4:'abc'}
with open('pickle_file','wb') as f:
    pickle.dump(dic, f)
    pickle.dump(dic1, f)
    pickle.dump(dic2, f)
    pickle.dump(dic3, f)
with open('pickle_file','rb') as f:
    ret = pickle.load(f)
    print(ret,type(ret))
    ret = pickle.load(f)
    print(ret,type(ret))
    ret = pickle.load(f)
    print(ret, type(ret))
    ret = pickle.load(f)
    print(ret, type(ret))

3.3   異常處理

with open('pickle_file','rb') as f:

    while True:

        try:

            ret = pickle.load(f)

            print(ret,type(ret))

        except EOFError:

            break
相關文章
相關標籤/搜索