常用模組(json/pickle/shelve/XML)
一、json模組(重點)
一種跨平臺的資料格式
也屬於序列化的一種方式
介紹模組之前,三個問題:
序列化是什麼?
我們把物件(變數)從記憶體中變成可儲存或傳輸的過程稱之為序列化。
反序列化又是什麼?
將硬碟上儲存的中間格式資料在還原為記憶體中的資料結構
為什麼要序列化?
1、持久保持狀態
2、跨平臺資料的互動
JSON是什麼? java script object notation 就是物件表示法 var obj = {"name":"egon"} 對於我們開發而言 json就是一種通用的資料格式 任何語言都能解析
js中的資料型別 在python中資料型別的對應關係
{} 字典 [] list string "" str int/float int/float true/false True/False null None
json格式的語法規範 最外層通常是一個字典或列表 {} or [] 只要你想寫一個json格式的資料 那麼最外層直接寫{} 字串必須是雙引號 你可以在裡面套任意多的層次
json模組的核心功能 dump dumps load loads 不帶s: 封裝了write 和 read
但多數實際開發中 用dumps 和 loads 較多
import json #序列化 # dic = {"a": '香港', "b": "重慶", "c": "上海"} # with open("c.json","wt",encoding="utf-8") as f: # f.write(json.dumps(dic)) # print(repr(s), type(s)) 反序列化 # with open("c.json","rt",encoding="utf-8") as f: # # print(f.read()) # d = json.loads(f.read()) # print(d)
兩個eg:
jsontext = """{ "users": [{ "name": "agon", "age": 68 }, { "name": "alex", "age": 57 } ] }""" # res = json.loads(jsontext) # print(res)
mydic = { "users": [{ "name": "agon", "age": 68 }, { "name": "alex", "age": 57 } ] } # with open("b.json","wt",encoding="utf-8") as f: # f.write(json.dumps(mydic)) # with open("b.json", "wt", encoding="utf-8") as f: # json.dump(mydic, f)
二、pickle模組
專用於python語言的序列化
pickle模組主要功能 dump load dumps loads dump是序列化 load反序列化 不帶s的是幫你封裝write read 更方便
load函式可以多次執行 每次load 都是往後在讀一個物件 如果沒有了就丟擲異常Ran out of input。
eg:
import pickle # 使用者註冊後得到的資料 name = "wwl" password = "123" height = 1.8 hobby = ["吃","喝","賭","飄",{1,2,3}] # with open("userdb.txt","wt",encoding="utf-8") as f: # text = "|".join([name,password,str(height)]) # f.write(text) # pickle支援python中所有的資料型別 user = {"name":name,"password":password,"height":height,"hobby":hobby,"test":3}
序列化的過程
# with open("userdb.pkl","ab") as f: # userbytes = pickle.dumps(user) # f.write(userbytes)
反序列化過程
# with open("userdb.pkl","rb") as f: # userbytes = f.read() # user = pickle.loads(userbytes) # print(user) # print(type(user))
#dump 直接序列化到檔案 # with open("userdb.pkl","ab") as f: # pickle.dump(user,f) #load 從檔案反序列化 with open("userdb.pkl","rb") as f: user = pickle.load(f) print(user) print(pickle.load(f)) print(pickle.load(f)) print(pickle.load(f))
Conclusion:
json vs pickle:
json:
優點:跨語言、體積小
缺點:只能支援int\str\list\tuple\dict
Pickle:
優點:專為python設計,支援python所有的資料型別
缺點:只能在python中使用,儲存資料佔空間大
三、shelve模組
shelve模組 也用於序列化
它於pickle不同之處在於 不需要關心檔案模式什麼的 直接把它當成一個字典來看待 它可以直接對資料進行修改 而不用覆蓋原來的資料 而pickle 你想要修改只能 用wb模式來覆蓋
序列化
import shelve f = shelve.open('shelve_test') # 開啟一個檔案 names = ["alex", "rain", "test"] info = {'name':'alex','age':22} f["names"] = names # 持久化列表 f['info_dic'] = info f.close()
反序列化
import shelve d = shelve.open('shelve_test',,writeback=True) # 開啟一個檔案 print(d['names']) print(d['info_dic'])d['names'].append('wwl')d.close() #del d['test'] #還可以刪除
四、XML模組 (可擴充套件的標記語言)
也是一種通用的資料格式 之所用用它也是因為跨平臺
xml是實現不同語言或程式之間進行資料交換的協議,跟json差不多,但json使用起來更簡單,不過,古時候,在json還沒誕生的黑暗年代,大家只能選擇用xml呀,至今很多傳統公司如金融行業的很多系統的介面還主要是xml。
例如:
<?xml version="1.0"?> <data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data>
重點還是語法格式 一、任何的起始標籤都必須有一個結束標籤。 <> </> 二、可以採用另一種簡化語法,可以在一個標籤中同時表示起始和結束標 籤。這種語法是在於符號之前緊跟一個斜線(/),XML 解析器會將其翻譯成<百度百科詞條></百度百科詞條>。例如<百度百科詞條/>。
三、標籤必須按合適的順序進行行巢狀,所以結束標籤必須按映象順序匹配 起始標籤。這好比是將起始和結束標籤看作是數學中的左右括號:在沒有關閉所有 的內部括號之前,是不不能關閉外面的括號的。 四、所有的特性都必須有值。 五、所有的特性都必須在值的周圍加上雙引號。
一個標籤的組成部分 <tagename 屬性名稱="屬性值">文字內容 </tagname>
單標籤的寫法 <tagename 屬性名稱="屬性值"/>
# 映象關閉順序例項
<a> <b> <c> </c> </b> </a>
把朋友的資訊寫成xml
<studentinfo>
<張三>
<age>20</age>
<gender>man</gender>
</張三>
<李四>
<age>20</age>
<gender>man</gender>
</李四>
</studentinfo>
用法:
import xml.etree.ElementTree as ElementTree # 解析d.xml tree = ElementTree.parse("d.xml") print(tree) # 獲取根標籤 rootTree = tree.getroot()
# 三種獲取標籤的方式 # 獲取所有人的年齡 iter是用於在全文範圍獲取標籤 # for item in rootTree.iter("age"): # # 一個標籤三個組成部分 # print(item.tag) # 標籤名稱 # print(item.attrib) # 標籤的屬性 # print(item.text) # 文字內容 # 第二種 從當前標籤的子標籤中找到一個名稱為age的標籤 如果有多個 找到的是第一個 # print(rootTree.find("age").attrib) # 第三種 從當前標籤的子標籤中找到所有名稱為age的標籤 # print(rootTree.findall("age"))
# 獲取單個屬性 stu = rootTree.find("stu") print(stu.get("age")) print(stu.get("name")) # 刪除子標籤 rootTree.remove(stu) # 新增子標籤 # 要先建立一個子標籤 newTag = ElementTree.Element("這是新標籤",{"一個屬性":"值"}) rootTree.append(newTag) # 寫入檔案 tree.write("f.xml",encoding="utf-8")
練習:
import xml.etree.ElementTree as ElementTree tree = ElementTree.parse("f.xml") rootTree = tree.getroot() users = [] for item in rootTree.iter("stu"): user = item.attrib print(user) gitem = item.find("girlfriend") user["girlfriend"] = gitem.attrib users.append(user) print(users)
Conclusion:
xml也是一種中間格式 也屬於序列化方式之一 與json相比較 同樣的資料 json會比xml 更小 效率更高 xml 需要根據文件結構 手動解析 而 json 直接轉物件