1. 程式人生 > >常用模組-pickle\json\xml\shelve\

常用模組-pickle\json\xml\shelve\

什麼是序列化?

將記憶體中的資料結構轉化為一種中間格式,並存儲到硬碟上 我們把物件(變數)從記憶體中變成可儲存或傳輸的過程稱之為序列化

為什麼要序列化?

就是為了將資料持久儲存 序列化之後,不僅可以把序列化後的內容寫入磁碟,還可以通過網路傳輸到別的機器上,如果收發的雙方約定好使用一種序列化的格式,那麼便打破了平臺/語言差異化帶來的限制,實現跨平臺資料互動.

反序列化?

將硬碟上儲存的中間格式資料再還原為記憶體中的資料結構

  • pickle模組
import pickle
# 使用者註冊後得到的資料
name = '高跟'
password = '123'
height = 1.5
hobbies =
['eat','drink','piao','du',{1,2,3}] # 按照我們之前的方法儲存 with open('userdb.txt','wt',encoding = 'utf-8') as f: test = '|'.join([name,password,str(height)]) f.write(text) # pickle支援python中所有的資料型別 user = {"name":name,"password":password,"height":height,"hobby":hobby,"test":3} # 序列化的過程pickle.dumps with open
('userdb.pkl','ab') as f: userbytes = pickle.dumps(user) f.write(userbytes) # 序列化pickle.dump with open('userdb.pkl','ab') as f: pickle.dump(user,f) '''dump和dumps的區別,dump幫你封裝了write的方法,更方便一些''' # pickle.loads 從檔案反序列化 with open('userdb.pkl','rb') as f: userbytes = f.read() user = pickle.loads(userbytes)
print(user) # pickle.loads 反序列化 with open('userdb.pkl','rb') as f: user = picklel.load(f) print(user) '''load和loads的區別,也是load封裝了read功能''' # 看到load封裝了read的功能,想為什麼不把開啟檔案也給封裝了呢,我們可以自己封裝一下 def myload(filename): #給一個引數,要開啟的檔案 with open(filename,'rb') as f: return pickle.load(f) # 以後直接自己寫的
  • shelve模組

shelve模組 也用於序列化 它不同於pickle之處在於不需要關心檔案模式,直接把它當成一個字典對待 它可以直接對資料進行修改 而不用覆蓋原來的資料 而pickle 你想要修改只能用wb模式來覆蓋

import shelve
user = {'name':'高跟'}
s = shelve.open('userdb.shv')
s['user'] = user
s.close()

s = shelve.open('userdb.shv',writeback = Trun) #writeback(寫回)引數預設為False 改為Trun,可以對資料進行修改
print(s['user'])
s['user']['age'] = 20
s.close()

pickle 和 shevle 序列化其實我們基本不用,因為他們序列化得到的資料只有python才能解析 通常企業開發不可能做一個單機程式,都是需要聯網進行計算機間的互動的 我們必須保證資料能夠跨平臺使用

  • json模組:重點 (jave script object notation)

對於開發而言,json就是一種通用的資料格式 任何語言都可以解析,所以它可以跨平臺使用

js中的資料型別 python資料型別
{} dict
[] list
string"" str
int/float int/float
true/false True/False
null None

json格式的語法規範:

  1. 最外層通常是一個字典或者列表
  2. 其實列表也不常用,只要你想寫一個json格式的資料,那麼最外層直接寫{}
  3. 字串必須時雙引號
  4. 可以再裡面套任意多的層次
  5. 寫json格式的語法,最好用json的格式化
# json模組的核心功能
# dump dumps load loads 和pickle的用法差不多

import json
# 序列化
dic = {'name':'alex','age':28,'sex':'male'}
print(type(dic))  #<class 'dict'>

j = json.dumps(dic)
print(type(j))    #<class 'str'>

# 反序列化
with open("a.json","rt",encoding = "utf-8") as f:
	res = json.loads(f.read())
	print(res)

with open("a.json","rt",encoding = "utf-8") as f:
	print(json.load(f))

直接解析字串的json為python物件

import json
# 直接解析字串的json為python物件
jsontext = """{
	"user":[{
		"name":"egon",
		"age":18
	},
	{
		"name":"alex",
		"age":58
	}]
}
"""
res = json.loads(jsontext)
print(res)

將python物件序列化為json格式寫入檔案

import json

mydic = {
	'user':[{
		'name':'egon',
		'age':18
	},
	{
		'name':'alex',
		'age':58
	}]
}
# json.dumps
with open('b.json','wt',encoding = 'ust-8') as f:
	f.write(json.dumps(mydic))
# json.dump
with open('b.json','wt',encoding = 'ust-8') as f:
	json.dump(mydic,f)
  • xml模組

XML 可擴充套件的標記語言 <></> 也是一種通用的資料格式,也是跨平臺 相比json比較複雜,xml比較早,所以很多寫的找的資料都是用的xml記錄的,我們在寫的時候建議使用json

學習的重點和語法格式:

  1. 任何的起始標籤都必須有一個結束標籤 <></>
  2. 可以採用另一種簡化語法,可以在一個標籤中同時表示起始和結束標籤。這種語法是在⼤於符號之前緊跟一個斜線</>,例如:<百度百科詞條></百度百科詞條>可以寫成<百度百科詞條/>
  3. 標籤必須按合適的順序進行巢狀,所以結束標籤必須按映象順序匹配起始標籤.
  4. 所有的特性都必須有值
  5. 所有特性都必須在值得周圍加上雙引號.
'''
一個標籤的組成部分
<tagename 屬性名稱 = '屬性值'>文字內容
</tagename>
單標籤的寫法
<tagename 屬性名稱 = '屬性值'/>

把你左右同學的資訊寫成xml
<studentinfo>
    <張三>
        <age>20</age>
        <gender>man</gender>
    </張三>
    <李四>
        <age>20</age>
        <gender>man</gender>
    </李四>
</studentinfo>

    總結 xml也是一種中間格式 也屬於序列化方式之一
    與json相比較
    同樣的資料  json會比xml 更小 效率更高
    xml 需要根據文件結構 手動解析 而json 直接轉物件

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

  • configparser模組

用於解析配置檔案的模組 配置檔案:包含配置程式資訊的檔案就是配置檔案 配置資訊:需要改,但不經常改的資訊 例如資料檔案的路徑

配置檔案中 只有兩種內容

  1. section分割槽
  2. option選項 就是一個key=value形式 我們一般用的最多的是get功能,用來從配置檔案中獲取一個配置選項
'''做一個登入 首先檢視配置檔案 是否又包含 使用者名稱和密碼 如果由直接登入 如果沒有就進行輸入使用者名稱密碼登入
    登入成功後 詢問是否要儲存密碼  如果是 寫入配置檔案'''

import configparser
# 建立一個解析器
config = configparser.ConfigParser()
# 讀取並解析test.cfg
config.read("test.cfg",encoding="utf-8")
# 獲取需要的資訊
# 獲取所有分割槽
print(config.sections())
# 獲取所有選項
print(config.options("user"))
# 獲取某個選項的值
print(config.get("path","DB_PATH"))
print(type(config.get("user","age")))

# # get返回的都是字串型別  如果需要轉換型別 直接使用get+對應的型別(bool int float)
print(type(config.getint("user","age")))
print(type(config.get("user","age")))

# 是否由某個選項
config.has_option()
# 是否由某個分割槽
config.has_section()

# 不太常用的
# 新增
config.add_section("server")
config.set("server","url","192.168.1.2")
# 刪除
config.remove_option("user","age")
# 修改
config.set("server","url","192.168.1.2")

# 寫回檔案中
with open("test.cfg", "wt", encoding="utf-8") as f:
    config.write(f)