常用模块(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 直接转对象