1. 程式人生 > >常用模組(json/pickle/shelve/XML)

常用模組(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 直接轉物件