第二十一篇 json,picklz,xml模块
Json模块
Json模块比较简单,仅有四个方法dumps()和loads()方法,dump()和load()方法,但是却非常的常用,实用性极强。
如果要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如xml,但更好的方法是序列化为JSON,因为json表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。
Json不仅是标准格式,而且比xml更快,还可以直接在web页面中读取,非常方便。
Json表示的对象就是标准的JavaScript语言的对象,Json和Python内置的数据类型对应如下:
Json类型 | Python内置类型 |
{} | dict |
[] | list |
"string" | str |
123/123.34 | int/float |
true/false | True / False |
null | None |
import json dic = {'name':'chen'} i = 8 s = 'hello' l = [1,2,3] # json.dumps 会把字符串里所有的单引号都变成双引号 data_dic = json.dumps(dic) # 第一步:把dic的值变成双引号,{"name":"chen"},第二步:再把这个值变成json的字符串:'{"name":"chen"}' print(data_dic) # {"name": "chen"} print(type(data_dic)) # <class 'str'> i = json.dumps(i) # 第一步:把i的值变成双引号,"8",第二步:再把这个值变成json的字符串:'"8"' print(i) # 8 print(type(i)) # <class 'str'> s = json.dumps(s) # 第一步:把s的值变成双引号,"hello",第二步:再把这个值变成json的字符串:'"hello"' print(s) # "hello" print(type(s)) # <class 'str'> l = json.dumps(l) print(l) # [1, 2, 3] print(type(l)) # <class 'str'> # 从上面的结果可以看到,json.dumps()首先会把所有数据类型的值都变成双引号(因为json只认双引号),然后再把这个值变成字符串
dumps()和loads()方法
# 上面已经把各种数据类型都通过json.dumps()方法处理成了json格式的字符串,然后把字符串写入到new_dic文件 # json.dumps()是-----序列化 dic = {'name':'chen'} dic_str = json.dumps(dic) f = open('new_dic','w', encoding = 'utf-8') f.write(dic_str) f.close # json.loads()是------反序列化 # 最后再读取new_dic内的文件 f_read = open('new_dic','r', encoding = 'utf-8') data = json.loads(f_read.read()) print(data) # {'name': 'chen'} print(type(data)) # <class 'dict'> print(data['name']) # chen
dump()和load()方法
# dump()和load()可以简化dumps()和loads()的处理过程 # 上面的如果要写一个字典到文件里,实现序列化,使用dumps()的代码如下: dic = {'name':'chen'} f = open('new_dic','w', encoding = 'utf-8') # 下面的两行会被dump()直接简化处理掉 dic_str = json.dumps(dic) f.write(dic_str) f.close() # 而如果使用dump()方法,代码如下: dic = {'name':'chen'} f = open('new_dic','w', encoding = 'utf-8') json.dump(dic,f) f.close() # 同理,如果想从文件里读取内容,实现反序列化,使用loads()代码如下: f_read = open('new_dic','r', encoding = 'utf-8') data = json.loads(f_read.read()) # 而如果使用load()方法,代码如下: f_read = open('new_dic','r', encoding = 'utf-8') data = json.load(f_read) print(data) # {'name': 'chen'} # 虽然dump()和load()可以简化dumps()和loads(),但是太定制化了,仅限于对文件的处理。 所以,建议在程序开发中还是使用dumps()和loads()方法,因为还有其他数据类型的处理呢。
XML模块
XML是实现不同语言或程序之间进行数据交换的协议,跟json作用差不多,但json使用起来更简单,不过,再远古时候,json未诞生的年代,只能用xml,所以,至今很多传统行业如金融行业的很多系统的接口主要还是xml.
xml文件内容
<data> <country name="Liechtenstein"> <--注释:country 是标签名, name是属性,用来解释标签用的--> <rank updated="yes">2</rank> <-- 2是text,文本--> <year updated="yes">2010</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year updated="yes">2013</year> <gdppc>59900</gdppc> <neighbor direction="N" name="Malaysia" /> </country> <country name="Panama"> <rank updated="yes">69</rank> <year updated="yes">2013</year> <gdppc>13600</gdppc> <neighbor direction="W" name="Costa Rica" /> <neighbor direction="E" name="Colombia" /> </country> </data>
Python处理xml文件
- 遍历xml文件
- getroot()方法
# 1. 先导入xml模块 import xml.etree.ElementTree as ET # 2. parse(): 读取xml数据并解析。parse是解析的意思 tree = ET.parse("tryxml") # tree是个对象,对象是个实体,可以调用属性和方法 # getroot(): root是根的意思,getroot()就是获取根节点 root = tree.getroot() # 获取对象的根节点 print(root) # 结果 <Element 'data' at 0x00E87330> #凡是有地址的,一定是对象,可以对他进行操作,可以对他进行遍历,可以看它里面的信息, # 对象的第一个属性tag,tag是标签的意思 print(root.tag) # 结果: data
2. tag 和 attrib 属性
#上面的root打印后是个对象,那么就可以对该对象进行遍历,看它里面都有什么 for i in root: print(i.tag) # 结果 country country country # 再对i对象进行遍历,看它下面都有什么 for i in root: for j in i: print(j.tag) # 结果 rank year gdppc neighbor neighbor rank year gdppc neighbor rank year gdppc neighbor neighbor # 上面都是只得到了标签,也就是tag属性,那怎么查看标签都有什么属性呢? # attrib 属性:获取标签的属性 for i in root: print(i.attrib) #结果 {'name': 'Liechtenstein'} {'name': 'Singapore'} {'name': 'Panama'} # 获取i对象下面标签的属性 for i in root: for j in i: print(j.attrib) #结果 {'updated': 'yes'} {'updated': 'yes'} {} {'direction': 'E', 'name': 'Austria'} {'direction': 'W', 'name': 'Switzerland'} {'updated': 'yes'} {'updated': 'yes'} {} {'direction': 'N', 'name': 'Malaysia'} {'updated': 'yes'} {'updated': 'yes'} {} {'direction': 'W', 'name': 'Costa Rica'} {'direction': 'E', 'name': 'Colombia'} # text属性:获取标签实际包裹的内容 for i in root: for j in i: print(j.text) # 结果 2 2010 141100 None None 5 2013 59900 None 69 2013 13600 None None
3. iter()方法
# 上面拿到的都是全部的数据,如果只想拿到所有的year节点的内容怎么取? # 只遍历所有year 节点,需要对根节点进行遍历 # iter()方法 for node in root.iter('year'): print(node.tag, node.text) # node.tag拿到year的标签; node.text 拿到year的内容 # 结果 year 2010 year 2013 year 2013
- 查找
# 三种查找方式 print(root.find('country')) # find找到第一个儿子就返回了 print(root.findall('country')) # findall找到全部儿子的才返回 print(root.find('rank')) # None 因为find找的是儿子,rank是孙子了,所以返回None
- 修改xml文件
# 修改 for node in root.iter('year'): # 先遍历 new_year = int(node.text) + 1 # 再取出要修改的值,进行修改 node.text = str(new_year) # 把新修改的text赋值给原来的text,实现修改功能 node.set("updated", "yes") # 对属性进行修改,给year 标签 加了属性 updated = yes # 上面只是修改成功了,但是并没有写入文件,所以还需要进行写入操作 # write():写入文件 tree.write("xmlabc.xml") # 写的时候重新取个名字,存为一个新的文件 tree.write("tryxml") # 覆盖原来的文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 修改后的xml文件 <data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year updated="yes">2011</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year updated="yes">2014</year> <gdppc>59900</gdppc> <neighbor direction="N" name="Malaysia" /> </country> <country name="Panama"> <rank updated="yes">69</rank> <year updated="yes">2014</year> <gdppc>13600</gdppc> <neighbor direction="W" name="Costa Rica" /> <neighbor direction="E" name="Colombia" /> </country> </data>
- 删除xml文件节点
# 删除node # findall():可以找多个对象 # find():找一个对象 # remove(): 删除对象 # write(): 写入文件 for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml')
- 创建xml数据
# 如何通过代码生成xml呢? # 1. 导入 xml模块 import xml.etree.ElementTree as ET # 2. 创建一个根节点,namelist是根节点的名字 # Element():创建根节点 # 实现的是<namelist> </namelist> new_xml = ET.Element("namelist") # 3. 在根节点里插入子节点 # SubElement(): 创建子节点 # SubElement(new_xml, "name", attrib={"enrolled": "yes"})里的new_xml 是要插入的目标;name是标签名;attrib 是 name标签的属性 name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"}) age = ET.SubElement(name, "age", attrib={"checked": "no"}) sex = ET.SubElement(name, "sex") # 4. 给标签写入内容 sex.text = 'male' age.text = '你多大了?' # 第二个name标签 name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"}) age = ET.SubElement(name2, "age") age.text = '19' # 5. 生成xml文档对象 et = ET.ElementTree(new_xml) # 生成文档数,这句话是必不可少的 et.write("test.xml", encoding="utf-8", xml_declaration=True) # 最后,将生成的文件,写入文件就行了 # 6. 打印生成的格式 ET.dump(new_xml)
- 通过代码创建的xml文档树
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version='1.0' encoding='utf-8'?> <namelist> <name enrolled="yes"> <age checked="no">你多大了?</age> <sex>female or male</sex> </name> <name enrolled="no"> <age>19</age> </name> </namelist>